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 *
180bbd860fSMichael Walshimport gen_robot_print as grp
1955302295SMichael Walshimport gen_robot_plug_in as grpi
206741f740SMichael Walshimport gen_robot_valid as grv
216741f740SMichael Walshimport gen_misc as gm
226741f740SMichael Walshimport gen_cmd as gc
2355302295SMichael Walshimport state as st
240bbd860fSMichael Walsh
250b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
260b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
270b93fbf8SMichael Walsh                            os.sep
280b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
290b93fbf8SMichael Walshimport run_keyword as rk
300bbd860fSMichael Walsh
316741f740SMichael Walsh# Program parameter processing.
326741f740SMichael Walsh# Assign all program parms to python variables which are global to this module.
336741f740SMichael Walshparm_list = BuiltIn().get_variable_value("${parm_list}")
346741f740SMichael Walshint_list = ['max_num_tests', 'boot_pass', 'boot_fail', 'quiet', 'test_mode',
356741f740SMichael Walsh            'debug']
366741f740SMichael Walshfor parm in parm_list:
376741f740SMichael Walsh    if parm in int_list:
386741f740SMichael Walsh        sub_cmd = "int(BuiltIn().get_variable_value(\"${" + parm +\
396741f740SMichael Walsh                  "}\", \"0\"))"
406741f740SMichael Walsh    else:
416741f740SMichael Walsh        sub_cmd = "BuiltIn().get_variable_value(\"${" + parm + "}\")"
426741f740SMichael Walsh    cmd_buf = parm + " = " + sub_cmd
436741f740SMichael Walsh    exec(cmd_buf)
440bbd860fSMichael Walsh
456741f740SMichael Walshif ffdc_dir_path_style == "":
466741f740SMichael Walsh    ffdc_dir_path_style = int(os.environ.get('FFDC_DIR_PATH_STYLE', '0'))
476741f740SMichael Walsh
486741f740SMichael Walsh# Set up boot data structures.
496741f740SMichael Walshboot_table = create_boot_table()
506741f740SMichael Walshvalid_boot_types = create_valid_boot_list(boot_table)
510b93fbf8SMichael Walsh
52e1e26448SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
53e1e26448SMichael Walsh# DB_Logging
54e1e26448SMichael Walshprogram_pid = os.getpid()
55e1e26448SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
56e1e26448SMichael Walsh
57e1e26448SMichael Walshboot_results_file_path = "/tmp/" + openbmc_nickname + ":pid_" +\
58e1e26448SMichael Walsh   str(master_pid) + ":boot_results"
59e1e26448SMichael Walshif os.path.isfile(boot_results_file_path):
600b93fbf8SMichael Walsh    # We've been called before in this run so we'll load the saved
610b93fbf8SMichael Walsh    # boot_results object.
620b93fbf8SMichael Walsh    boot_results = pickle.load(open(boot_results_file_path, 'rb'))
630b93fbf8SMichael Walshelse:
646741f740SMichael Walsh    boot_results = boot_results(boot_table, boot_pass, boot_fail)
650b93fbf8SMichael Walsh
666741f740SMichael Walshboot_lists = read_boot_lists()
676741f740SMichael Walshlast_ten = []
686741f740SMichael Walsh# Convert these program parms to more useable lists.
696741f740SMichael Walshboot_list = filter(None, boot_list.split(":"))
706741f740SMichael Walshboot_stack = filter(None, boot_stack.split(":"))
716741f740SMichael Walsh
726741f740SMichael Walshstate = st.return_default_state()
736741f740SMichael Walshcp_setup_called = 0
746741f740SMichael Walshnext_boot = ""
756741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
766741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
776741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
786741f740SMichael Walshffdc_list_file_path = base_tool_dir_path + openbmc_nickname + "/FFDC_FILE_LIST"
796741f740SMichael Walshboot_success = 0
806741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
816741f740SMichael Walshif status_dir_path != "":
826741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
830b93fbf8SMichael Walshdefault_power_on = "REST Power On"
840b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
856741f740SMichael Walshboot_count = 0
860bbd860fSMichael Walsh
870bbd860fSMichael Walsh
880bbd860fSMichael Walsh###############################################################################
890bbd860fSMichael Walshdef plug_in_setup():
900bbd860fSMichael Walsh
910bbd860fSMichael Walsh    r"""
920bbd860fSMichael Walsh    Initialize all plug-in environment variables for use by the plug-in
930bbd860fSMichael Walsh    programs.
940bbd860fSMichael Walsh    """
950bbd860fSMichael Walsh
966741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
970bbd860fSMichael Walsh    if boot_pass > 1:
980bbd860fSMichael Walsh        test_really_running = 1
990bbd860fSMichael Walsh    else:
1000bbd860fSMichael Walsh        test_really_running = 0
1010bbd860fSMichael Walsh
1020bbd860fSMichael Walsh    seconds = time.time()
1030bbd860fSMichael Walsh    loc_time = time.localtime(seconds)
1040bbd860fSMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
1050bbd860fSMichael Walsh
1066741f740SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
1070bbd860fSMichael Walsh
1086741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
1096741f740SMichael Walsh                                  test_really_running)
1106741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
1116741f740SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
1120bbd860fSMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
11355302295SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
1144c9a6453SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
1154c9a6453SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
1164c9a6453SMichael Walsh                                  ffdc_list_file_path)
1176741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
1186741f740SMichael Walsh                                  ffdc_dir_path_style)
1196741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
1206741f740SMichael Walsh                                  ffdc_check)
1216741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
1226741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
1236741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
1246741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
1254c9a6453SMichael Walsh
1260bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
1270bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
1280bbd860fSMichael Walsh    # element in additional_values.
1290bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
1300bbd860fSMichael Walsh                         "boot_fail", "test_really_running", "program_pid",
1314c9a6453SMichael Walsh                         "master_pid", "ffdc_prefix", "ffdc_dir_path",
13255302295SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
13355302295SMichael Walsh                         "ffdc_list_file_path"]
1340bbd860fSMichael Walsh
1350bbd860fSMichael Walsh    plug_in_vars = parm_list + additional_values
1360bbd860fSMichael Walsh
1370bbd860fSMichael Walsh    for var_name in plug_in_vars:
1380bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
1390bbd860fSMichael Walsh        var_name = var_name.upper()
1400bbd860fSMichael Walsh        if var_value is None:
1410bbd860fSMichael Walsh            var_value = ""
1426741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
1430bbd860fSMichael Walsh
1440bbd860fSMichael Walsh    if debug:
1456741f740SMichael Walsh        shell_rc, out_buf = \
1466741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
1470bbd860fSMichael Walsh
1480bbd860fSMichael Walsh###############################################################################
1490bbd860fSMichael Walsh
1500bbd860fSMichael Walsh
1510bbd860fSMichael Walsh###############################################################################
1526741f740SMichael Walshdef setup():
1530bbd860fSMichael Walsh
1540bbd860fSMichael Walsh    r"""
1556741f740SMichael Walsh    Do general program setup tasks.
1560bbd860fSMichael Walsh    """
1570bbd860fSMichael Walsh
1586741f740SMichael Walsh    global cp_setup_called
1590bbd860fSMichael Walsh
1606741f740SMichael Walsh    grp.rqprintn()
1616741f740SMichael Walsh
1626741f740SMichael Walsh    validate_parms()
1636741f740SMichael Walsh
1646741f740SMichael Walsh    grp.rqprint_pgm_header()
1656741f740SMichael Walsh
1666741f740SMichael Walsh    plug_in_setup()
1676741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1686741f740SMichael Walsh        call_point='setup')
1696741f740SMichael Walsh    if rc != 0:
1706741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
1716741f740SMichael Walsh        grp.rprint_error_report(error_message)
1726741f740SMichael Walsh        BuiltIn().fail(error_message)
1736741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
1746741f740SMichael Walsh    # the cleanup plug-in call point.
1756741f740SMichael Walsh    cp_setup_called = 1
1766741f740SMichael Walsh
1776741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
1786741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
1796741f740SMichael Walsh
1806741f740SMichael Walsh    grp.rdprint_var(boot_table, 1)
1816741f740SMichael Walsh    grp.rdprint_var(boot_lists)
1820bbd860fSMichael Walsh
1830bbd860fSMichael Walsh###############################################################################
1840bbd860fSMichael Walsh
1850bbd860fSMichael Walsh
1860bbd860fSMichael Walsh###############################################################################
1876741f740SMichael Walshdef validate_parms():
1880bbd860fSMichael Walsh
1890bbd860fSMichael Walsh    r"""
1906741f740SMichael Walsh    Validate all program parameters.
1910bbd860fSMichael Walsh    """
1920bbd860fSMichael Walsh
1936741f740SMichael Walsh    grp.rqprintn()
1940bbd860fSMichael Walsh
1956741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
1966741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
1976741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
1986741f740SMichael Walsh    if os_host != "":
1996741f740SMichael Walsh        grv.rvalid_value("os_username")
2006741f740SMichael Walsh        grv.rvalid_value("os_password")
2010bbd860fSMichael Walsh
2026741f740SMichael Walsh    if pdu_host != "":
2036741f740SMichael Walsh        grv.rvalid_value("pdu_username")
2046741f740SMichael Walsh        grv.rvalid_value("pdu_password")
2056741f740SMichael Walsh    grv.rvalid_integer("pdu_slot_no")
2066741f740SMichael Walsh    if openbmc_serial_host != "":
2076741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
2086741f740SMichael Walsh    grv.rvalid_integer("max_num_tests")
2096741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
2106741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
2116741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
2126741f740SMichael Walsh
2136741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
2146741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
2156741f740SMichael Walsh                                  plug_in_packages_list)
2166741f740SMichael Walsh
2176741f740SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0:
2186741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
2196741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
2206741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
2216741f740SMichael Walsh
2226741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
2236741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
2246741f740SMichael Walsh
2256741f740SMichael Walsh    return
2260bbd860fSMichael Walsh
2270bbd860fSMichael Walsh###############################################################################
2280bbd860fSMichael Walsh
2290bbd860fSMichael Walsh
2300bbd860fSMichael Walsh###############################################################################
2316741f740SMichael Walshdef my_get_state():
2320bbd860fSMichael Walsh
2330bbd860fSMichael Walsh    r"""
2346741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
2350bbd860fSMichael Walsh    """
2360bbd860fSMichael Walsh
2376741f740SMichael Walsh    global state
2386741f740SMichael Walsh
2396741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
2406741f740SMichael Walsh
2416741f740SMichael Walsh    grp.rqprint_timen("Getting system state.")
2426741f740SMichael Walsh    if test_mode:
2436741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
2446741f740SMichael Walsh    else:
2456741f740SMichael Walsh        state = st.get_state(req_states=req_states, quiet=0)
2466741f740SMichael Walsh    grp.rprint_var(state)
247341c21ebSMichael Walsh
248341c21ebSMichael Walsh###############################################################################
249341c21ebSMichael Walsh
250341c21ebSMichael Walsh
251341c21ebSMichael Walsh###############################################################################
2526741f740SMichael Walshdef select_boot():
253341c21ebSMichael Walsh
254341c21ebSMichael Walsh    r"""
255341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
256341c21ebSMichael Walsh    chosen boot type.
257341c21ebSMichael Walsh
258341c21ebSMichael Walsh    Description of arguments:
2596741f740SMichael Walsh    state  The state of the machine.
260341c21ebSMichael Walsh    """
261341c21ebSMichael Walsh
26230dadae2SMichael Walsh    global boot_stack
26330dadae2SMichael Walsh
2646741f740SMichael Walsh    grp.rprint_timen("Selecting a boot test.")
2656741f740SMichael Walsh
2666741f740SMichael Walsh    my_get_state()
2676741f740SMichael Walsh
2686741f740SMichael Walsh    stack_popped = 0
2696741f740SMichael Walsh    if len(boot_stack) > 0:
2706741f740SMichael Walsh        stack_popped = 1
2716741f740SMichael Walsh        grp.rprint_dashes()
2726741f740SMichael Walsh        grp.rprint_var(boot_stack)
2736741f740SMichael Walsh        grp.rprint_dashes()
2746741f740SMichael Walsh        boot_candidate = boot_stack.pop()
2756741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
2766741f740SMichael Walsh            grp.rprint_timen("The machine state is valid for a '" +
2776741f740SMichael Walsh                             boot_candidate + "' boot test.")
2786741f740SMichael Walsh            grp.rprint_dashes()
2796741f740SMichael Walsh            grp.rprint_var(boot_stack)
2806741f740SMichael Walsh            grp.rprint_dashes()
2816741f740SMichael Walsh            return boot_candidate
282341c21ebSMichael Walsh        else:
2836741f740SMichael Walsh            grp.rprint_timen("The machine state is not valid for a '" +
2846741f740SMichael Walsh                             boot_candidate + "' boot test.")
2856741f740SMichael Walsh            boot_stack.append(boot_candidate)
2866741f740SMichael Walsh            popped_boot = boot_candidate
2876741f740SMichael Walsh
2886741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
2896741f740SMichael Walsh    boot_candidates = []
2906741f740SMichael Walsh    for boot_candidate in boot_list:
2916741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
2926741f740SMichael Walsh            if stack_popped:
2936741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
2946741f740SMichael Walsh                   boot_table[popped_boot]['start']):
2956741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
296341c21ebSMichael Walsh            else:
2976741f740SMichael Walsh                boot_candidates.append(boot_candidate)
2986741f740SMichael Walsh
2996741f740SMichael Walsh    if len(boot_candidates) == 0:
3006741f740SMichael Walsh        grp.rprint_timen("The user's boot list contained no boot tests" +
3016741f740SMichael Walsh                         " which are valid for the current machine state.")
3026741f740SMichael Walsh        boot_candidate = default_power_on
3036741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
3046741f740SMichael Walsh            boot_candidate = default_power_off
3056741f740SMichael Walsh        boot_candidates.append(boot_candidate)
3066741f740SMichael Walsh        grp.rprint_timen("Using default '" + boot_candidate +
3076741f740SMichael Walsh                         "' boot type to transtion to valid state.")
3086741f740SMichael Walsh
3096741f740SMichael Walsh    grp.rdprint_var(boot_candidates)
3106741f740SMichael Walsh
3116741f740SMichael Walsh    # Randomly select a boot from the candidate list.
3126741f740SMichael Walsh    boot = random.choice(boot_candidates)
313341c21ebSMichael Walsh
314341c21ebSMichael Walsh    return boot
3150bbd860fSMichael Walsh
3160bbd860fSMichael Walsh###############################################################################
31755302295SMichael Walsh
31855302295SMichael Walsh
31955302295SMichael Walsh###############################################################################
320341c21ebSMichael Walshdef print_last_boots():
321341c21ebSMichael Walsh
322341c21ebSMichael Walsh    r"""
323341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
324341c21ebSMichael Walsh    """
325341c21ebSMichael Walsh
326341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
327341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
328341c21ebSMichael Walsh    grp.rqprintn("Last 10 boots:\n")
329341c21ebSMichael Walsh
330341c21ebSMichael Walsh    for boot_entry in last_ten:
331341c21ebSMichael Walsh        grp.rqprint(boot_entry)
332341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
333341c21ebSMichael Walsh
334341c21ebSMichael Walsh###############################################################################
335341c21ebSMichael Walsh
336341c21ebSMichael Walsh
337341c21ebSMichael Walsh###############################################################################
338341c21ebSMichael Walshdef print_defect_report():
339341c21ebSMichael Walsh
340341c21ebSMichael Walsh    r"""
341341c21ebSMichael Walsh    Print a defect report.
342341c21ebSMichael Walsh    """
343341c21ebSMichael Walsh
344341c21ebSMichael Walsh    grp.rqprintn()
345341c21ebSMichael Walsh    # indent=0, width=90, linefeed=1, char="="
346341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
347341c21ebSMichael Walsh    grp.rqprintn("Copy this data to the defect:\n")
348341c21ebSMichael Walsh
349341c21ebSMichael Walsh    grp.rqpvars(*parm_list)
350341c21ebSMichael Walsh
351341c21ebSMichael Walsh    grp.rqprintn()
352341c21ebSMichael Walsh
353341c21ebSMichael Walsh    print_last_boots()
354341c21ebSMichael Walsh    grp.rqprintn()
355341c21ebSMichael Walsh    grp.rqpvar(state)
356341c21ebSMichael Walsh
357341c21ebSMichael Walsh    # At some point I'd like to have the 'Call FFDC Methods' return a list
358341c21ebSMichael Walsh    # of files it has collected.  In that case, the following "ls" command
359341c21ebSMichael Walsh    # would no longer be needed.  For now, however, glob shows the files
360341c21ebSMichael Walsh    # named in FFDC_LIST_FILE_PATH so I will refrain from printing those
361341c21ebSMichael Walsh    # out (so we don't see duplicates in the list).
362341c21ebSMichael Walsh
363341c21ebSMichael Walsh    LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}")
364341c21ebSMichael Walsh
365341c21ebSMichael Walsh    output = '\n'.join(glob.glob(LOG_PREFIX + '*'))
366341c21ebSMichael Walsh    try:
3676741f740SMichael Walsh        ffdc_list = open(ffdc_list_file_path, 'r')
368341c21ebSMichael Walsh    except IOError:
369341c21ebSMichael Walsh        ffdc_list = ""
370341c21ebSMichael Walsh
371341c21ebSMichael Walsh    grp.rqprintn()
372341c21ebSMichael Walsh    grp.rqprintn("FFDC data files:")
373341c21ebSMichael Walsh    if status_file_path != "":
374341c21ebSMichael Walsh        grp.rqprintn(status_file_path)
375341c21ebSMichael Walsh
376341c21ebSMichael Walsh    grp.rqprintn(output)
377341c21ebSMichael Walsh    # grp.rqprintn(ffdc_list)
378341c21ebSMichael Walsh    grp.rqprintn()
379341c21ebSMichael Walsh
380341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
381341c21ebSMichael Walsh
382341c21ebSMichael Walsh###############################################################################
3836741f740SMichael Walsh
3846741f740SMichael Walsh
3856741f740SMichael Walsh###############################################################################
3866741f740SMichael Walshdef my_ffdc():
3876741f740SMichael Walsh
3886741f740SMichael Walsh    r"""
3896741f740SMichael Walsh    Collect FFDC data.
3906741f740SMichael Walsh    """
3916741f740SMichael Walsh
3926741f740SMichael Walsh    global state
3936741f740SMichael Walsh
3946741f740SMichael Walsh    plug_in_setup()
3956741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
3966741f740SMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=1)
3976741f740SMichael Walsh
3986741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
3996741f740SMichael Walsh
4006741f740SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
4016741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
4026741f740SMichael Walsh
4036741f740SMichael Walsh    cmd_buf = ["FFDC", "ffdc_prefix=" + AUTOBOOT_FFDC_PREFIX]
4046741f740SMichael Walsh    grp.rpissuing_keyword(cmd_buf)
4056741f740SMichael Walsh    BuiltIn().run_keyword(*cmd_buf)
4066741f740SMichael Walsh
4076741f740SMichael Walsh    my_get_state()
4086741f740SMichael Walsh
4096741f740SMichael Walsh    print_defect_report()
4106741f740SMichael Walsh
4116741f740SMichael Walsh###############################################################################
4126741f740SMichael Walsh
4136741f740SMichael Walsh
4146741f740SMichael Walsh###############################################################################
4156741f740SMichael Walshdef print_test_start_message(boot_keyword):
4166741f740SMichael Walsh
4176741f740SMichael Walsh    r"""
4186741f740SMichael Walsh    Print a message indicating what boot test is about to run.
4196741f740SMichael Walsh
4206741f740SMichael Walsh    Description of arguments:
4216741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
4226741f740SMichael Walsh                  (e.g. "BMC Power On").
4236741f740SMichael Walsh    """
4246741f740SMichael Walsh
4256741f740SMichael Walsh    global last_ten
4266741f740SMichael Walsh
4276741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
4286741f740SMichael Walsh    grp.rqprint(doing_msg)
4296741f740SMichael Walsh
4306741f740SMichael Walsh    last_ten.append(doing_msg)
4316741f740SMichael Walsh
4326741f740SMichael Walsh    if len(last_ten) > 10:
4336741f740SMichael Walsh        del last_ten[0]
4346741f740SMichael Walsh
4356741f740SMichael Walsh###############################################################################
4366741f740SMichael Walsh
4376741f740SMichael Walsh
4386741f740SMichael Walsh###############################################################################
4396741f740SMichael Walshdef run_boot(boot):
4406741f740SMichael Walsh
4416741f740SMichael Walsh    r"""
4426741f740SMichael Walsh    Run the specified boot.
4436741f740SMichael Walsh
4446741f740SMichael Walsh    Description of arguments:
4456741f740SMichael Walsh    boot  The name of the boot test to be performed.
4466741f740SMichael Walsh    """
4476741f740SMichael Walsh
4486741f740SMichael Walsh    global state
4496741f740SMichael Walsh
4506741f740SMichael Walsh    print_test_start_message(boot)
4516741f740SMichael Walsh
4526741f740SMichael Walsh    plug_in_setup()
4536741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
4546741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
4556741f740SMichael Walsh    if rc != 0:
4566741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
4576741f740SMichael Walsh            gp.sprint_var(rc, 1)
4586741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
4596741f740SMichael Walsh
4606741f740SMichael Walsh    if test_mode:
4616741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
4626741f740SMichael Walsh        # required end state to the default state value.
46330dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
4646741f740SMichael Walsh    else:
4656741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
4666741f740SMichael Walsh        # caller.
4676741f740SMichael Walsh
4686741f740SMichael Walsh        grp.rprintn()
4696741f740SMichael Walsh
4706741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
4710b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
4720b93fbf8SMichael Walsh                               boot_table[boot]['method'])
4736741f740SMichael Walsh
4746741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
4756741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
47630dadae2SMichael Walsh            plug_in_setup()
47730dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
47830dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
47930dadae2SMichael Walsh            if rc != 0:
4800b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
4810b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
48230dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
4836741f740SMichael Walsh        else:
4846741f740SMichael Walsh            match_state = st.anchor_state(state)
4856741f740SMichael Walsh            del match_state['epoch_seconds']
4866741f740SMichael Walsh            # Wait for the state to change in any way.
4876741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
4886741f740SMichael Walsh                          interval="3 seconds", invert=1)
4896741f740SMichael Walsh
4906741f740SMichael Walsh        grp.rprintn()
4916741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
4926741f740SMichael Walsh            boot_timeout = power_off_timeout
4936741f740SMichael Walsh        else:
4946741f740SMichael Walsh            boot_timeout = power_on_timeout
4956741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
4966741f740SMichael Walsh                      interval="3 seconds")
4976741f740SMichael Walsh
4986741f740SMichael Walsh    plug_in_setup()
4996741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
5006741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
5016741f740SMichael Walsh    if rc != 0:
5026741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
5036741f740SMichael Walsh            gp.sprint_var(rc, 1)
5046741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
5056741f740SMichael Walsh
5066741f740SMichael Walsh###############################################################################
5076741f740SMichael Walsh
5086741f740SMichael Walsh
5096741f740SMichael Walsh###############################################################################
5106741f740SMichael Walshdef test_loop_body():
5116741f740SMichael Walsh
5126741f740SMichael Walsh    r"""
5136741f740SMichael Walsh    The main loop body for the loop in main_py.
5146741f740SMichael Walsh
5156741f740SMichael Walsh    Description of arguments:
5166741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
5176741f740SMichael Walsh    """
5186741f740SMichael Walsh
5196741f740SMichael Walsh    global boot_count
5206741f740SMichael Walsh    global state
5216741f740SMichael Walsh    global next_boot
5226741f740SMichael Walsh    global boot_success
5236741f740SMichael Walsh
5246741f740SMichael Walsh    grp.rqprintn()
5256741f740SMichael Walsh
5266741f740SMichael Walsh    boot_count += 1
5276741f740SMichael Walsh
5286741f740SMichael Walsh    next_boot = select_boot()
5296741f740SMichael Walsh
5306741f740SMichael Walsh    grp.rqprint_timen("Starting boot " + str(boot_count) + ".")
5316741f740SMichael Walsh
5326741f740SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
5336741f740SMichael Walsh    try:
5346741f740SMichael Walsh        os.remove(ffdc_list_file_path)
5356741f740SMichael Walsh    except OSError:
5366741f740SMichael Walsh        pass
5376741f740SMichael Walsh
5386741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
5396741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
5406741f740SMichael Walsh    if boot_status == "FAIL":
5416741f740SMichael Walsh        grp.rprint(msg)
5426741f740SMichael Walsh
5436741f740SMichael Walsh    grp.rqprintn()
5446741f740SMichael Walsh    if boot_status == "PASS":
5456741f740SMichael Walsh        boot_success = 1
5466741f740SMichael Walsh        grp.rqprint_timen("BOOT_SUCCESS: \"" + next_boot + "\" succeeded.")
5476741f740SMichael Walsh    else:
5486741f740SMichael Walsh        boot_success = 0
5496741f740SMichael Walsh        grp.rqprint_timen("BOOT_FAILED: \"" + next_boot + "\" failed.")
5506741f740SMichael Walsh
5516741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
5526741f740SMichael Walsh
5536741f740SMichael Walsh    plug_in_setup()
5546741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
5556741f740SMichael Walsh    # failure.
5566741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5576741f740SMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=1)
5586741f740SMichael Walsh
5596741f740SMichael Walsh    plug_in_setup()
5606741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5616741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
5626741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
5636741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
5646741f740SMichael Walsh        cmd_buf = ["my_ffdc"]
5656741f740SMichael Walsh        grp.rpissuing_keyword(cmd_buf)
5666741f740SMichael Walsh        BuiltIn().run_keyword_and_continue_on_failure(*cmd_buf)
5676741f740SMichael Walsh
568*952f9b09SMichael Walsh    boot_results.print_report()
569*952f9b09SMichael Walsh    grp.rqprint_timen("Finished boot " + str(boot_count) + ".")
570*952f9b09SMichael Walsh
5716741f740SMichael Walsh    plug_in_setup()
5726741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5736741f740SMichael Walsh        call_point='stop_check')
5746741f740SMichael Walsh    if rc != 0:
5756741f740SMichael Walsh        error_message = "Stopping as requested by user.\n"
5766741f740SMichael Walsh        grp.rprint_error_report(error_message)
5776741f740SMichael Walsh        BuiltIn().fail(error_message)
5786741f740SMichael Walsh
5796741f740SMichael Walsh    return True
5806741f740SMichael Walsh
5816741f740SMichael Walsh###############################################################################
5826741f740SMichael Walsh
5836741f740SMichael Walsh
5846741f740SMichael Walsh###############################################################################
5856741f740SMichael Walshdef program_teardown():
5866741f740SMichael Walsh
5876741f740SMichael Walsh    r"""
5886741f740SMichael Walsh    Clean up after this program.
5896741f740SMichael Walsh    """
5906741f740SMichael Walsh
5916741f740SMichael Walsh    if cp_setup_called:
5926741f740SMichael Walsh        plug_in_setup()
5936741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5946741f740SMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=1)
5956741f740SMichael Walsh
5960b93fbf8SMichael Walsh    # Save boot_results object to a file in case it is needed again.
5970b93fbf8SMichael Walsh    grp.rprint_timen("Saving boot_results to the following path.")
5980b93fbf8SMichael Walsh    grp.rprint_var(boot_results_file_path)
5990b93fbf8SMichael Walsh    pickle.dump(boot_results, open(boot_results_file_path, 'wb'),
6000b93fbf8SMichael Walsh                pickle.HIGHEST_PROTOCOL)
6010b93fbf8SMichael Walsh
6026741f740SMichael Walsh###############################################################################
6036741f740SMichael Walsh
6046741f740SMichael Walsh
6056741f740SMichael Walsh###############################################################################
6066741f740SMichael Walshdef main_py():
6076741f740SMichael Walsh
6086741f740SMichael Walsh    r"""
6096741f740SMichael Walsh    Do main program processing.
6106741f740SMichael Walsh    """
6116741f740SMichael Walsh
6126741f740SMichael Walsh    setup()
6136741f740SMichael Walsh
6146741f740SMichael Walsh    # Process caller's boot_stack.
6156741f740SMichael Walsh    while (len(boot_stack) > 0):
6166741f740SMichael Walsh        test_loop_body()
6176741f740SMichael Walsh
61830dadae2SMichael Walsh    grp.rprint_timen("Finished processing stack.")
61930dadae2SMichael Walsh
6206741f740SMichael Walsh    # Process caller's boot_list.
6216741f740SMichael Walsh    if len(boot_list) > 0:
6226741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
6236741f740SMichael Walsh            test_loop_body()
6246741f740SMichael Walsh
6256741f740SMichael Walsh    grp.rqprint_timen("Completed all requested boot tests.")
6266741f740SMichael Walsh
6276741f740SMichael Walsh###############################################################################
628