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
7*0b93fbf8SMichael Walshimport os
8*0b93fbf8SMichael Walshimport imp
9*0b93fbf8SMichael Walshimport time
10*0b93fbf8SMichael Walshimport glob
11*0b93fbf8SMichael Walshimport random
12*0b93fbf8SMichael Walshimport cPickle as pickle
13*0b93fbf8SMichael Walsh
14*0b93fbf8SMichael Walshfrom robot.utils import DotDict
15*0b93fbf8SMichael Walshfrom robot.libraries.BuiltIn import BuiltIn
16*0b93fbf8SMichael 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
25*0b93fbf8SMichael Walshbase_path = os.path.dirname(os.path.dirname(
26*0b93fbf8SMichael Walsh                            imp.find_module("gen_robot_print")[1])) +\
27*0b93fbf8SMichael Walsh                            os.sep
28*0b93fbf8SMichael Walshsys.path.append(base_path + "extended/")
29*0b93fbf8SMichael 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)
51*0b93fbf8SMichael Walsh
52*0b93fbf8SMichael Walshboot_results_file_path = "/tmp/" + openbmc_nickname + "_boot_results"
53*0b93fbf8SMichael Walshif (boot_pass > 0 or boot_fail > 0) and \
54*0b93fbf8SMichael Walsh   os.path.isfile(boot_results_file_path):
55*0b93fbf8SMichael Walsh    # We've been called before in this run so we'll load the saved
56*0b93fbf8SMichael Walsh    # boot_results object.
57*0b93fbf8SMichael Walsh    boot_results = pickle.load(open(boot_results_file_path, 'rb'))
58*0b93fbf8SMichael Walshelse:
596741f740SMichael Walsh    boot_results = boot_results(boot_table, boot_pass, boot_fail)
60*0b93fbf8SMichael Walsh
616741f740SMichael Walshboot_lists = read_boot_lists()
626741f740SMichael Walshlast_ten = []
636741f740SMichael Walsh# Convert these program parms to more useable lists.
646741f740SMichael Walshboot_list = filter(None, boot_list.split(":"))
656741f740SMichael Walshboot_stack = filter(None, boot_stack.split(":"))
666741f740SMichael Walsh
676741f740SMichael Walshstate = st.return_default_state()
686741f740SMichael Walshcp_setup_called = 0
696741f740SMichael Walshnext_boot = ""
706741f740SMichael Walshbase_tool_dir_path = os.path.normpath(os.environ.get(
716741f740SMichael Walsh    'AUTOBOOT_BASE_TOOL_DIR_PATH', "/tmp")) + os.sep
726741f740SMichael Walshffdc_dir_path = os.path.normpath(os.environ.get('FFDC_DIR_PATH', '')) + os.sep
736741f740SMichael Walshffdc_list_file_path = base_tool_dir_path + openbmc_nickname + "/FFDC_FILE_LIST"
746741f740SMichael Walshboot_success = 0
756741f740SMichael Walsh# Setting master_pid correctly influences the behavior of plug-ins like
766741f740SMichael Walsh# DB_Logging
776741f740SMichael Walshprogram_pid = os.getpid()
786741f740SMichael Walshmaster_pid = os.environ.get('AUTOBOOT_MASTER_PID', program_pid)
796741f740SMichael Walshstatus_dir_path = os.environ.get('STATUS_DIR_PATH', "")
806741f740SMichael Walshif status_dir_path != "":
816741f740SMichael Walsh    status_dir_path = os.path.normpath(status_dir_path) + os.sep
82*0b93fbf8SMichael Walshdefault_power_on = "REST Power On"
83*0b93fbf8SMichael Walshdefault_power_off = "REST Power Off"
846741f740SMichael Walshboot_count = 0
850bbd860fSMichael Walsh
860bbd860fSMichael Walsh
870bbd860fSMichael Walsh###############################################################################
880bbd860fSMichael Walshdef plug_in_setup():
890bbd860fSMichael Walsh
900bbd860fSMichael Walsh    r"""
910bbd860fSMichael Walsh    Initialize all plug-in environment variables for use by the plug-in
920bbd860fSMichael Walsh    programs.
930bbd860fSMichael Walsh    """
940bbd860fSMichael Walsh
956741f740SMichael Walsh    boot_pass, boot_fail = boot_results.return_total_pass_fail()
960bbd860fSMichael Walsh    if boot_pass > 1:
970bbd860fSMichael Walsh        test_really_running = 1
980bbd860fSMichael Walsh    else:
990bbd860fSMichael Walsh        test_really_running = 0
1000bbd860fSMichael Walsh
1010bbd860fSMichael Walsh    seconds = time.time()
1020bbd860fSMichael Walsh    loc_time = time.localtime(seconds)
1030bbd860fSMichael Walsh    time_string = time.strftime("%y%m%d.%H%M%S.", loc_time)
1040bbd860fSMichael Walsh
1056741f740SMichael Walsh    ffdc_prefix = openbmc_nickname + "." + time_string
1060bbd860fSMichael Walsh
1076741f740SMichael Walsh    BuiltIn().set_global_variable("${test_really_running}",
1086741f740SMichael Walsh                                  test_really_running)
1096741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_type_desc}", next_boot)
1106741f740SMichael Walsh    BuiltIn().set_global_variable("${master_pid}", master_pid)
1110bbd860fSMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH}", ffdc_dir_path)
11255302295SMichael Walsh    BuiltIn().set_global_variable("${STATUS_DIR_PATH}", status_dir_path)
1134c9a6453SMichael Walsh    BuiltIn().set_global_variable("${BASE_TOOL_DIR_PATH}", base_tool_dir_path)
1144c9a6453SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LIST_FILE_PATH}",
1154c9a6453SMichael Walsh                                  ffdc_list_file_path)
1166741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_DIR_PATH_STYLE}",
1176741f740SMichael Walsh                                  ffdc_dir_path_style)
1186741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_CHECK}",
1196741f740SMichael Walsh                                  ffdc_check)
1206741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_pass}", boot_pass)
1216741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_fail}", boot_fail)
1226741f740SMichael Walsh    BuiltIn().set_global_variable("${boot_success}", boot_success)
1236741f740SMichael Walsh    BuiltIn().set_global_variable("${ffdc_prefix}", ffdc_prefix)
1244c9a6453SMichael Walsh
1250bbd860fSMichael Walsh    # For each program parameter, set the corresponding AUTOBOOT_ environment
1260bbd860fSMichael Walsh    # variable value.  Also, set an AUTOBOOT_ environment variable for every
1270bbd860fSMichael Walsh    # element in additional_values.
1280bbd860fSMichael Walsh    additional_values = ["boot_type_desc", "boot_success", "boot_pass",
1290bbd860fSMichael Walsh                         "boot_fail", "test_really_running", "program_pid",
1304c9a6453SMichael Walsh                         "master_pid", "ffdc_prefix", "ffdc_dir_path",
13155302295SMichael Walsh                         "status_dir_path", "base_tool_dir_path",
13255302295SMichael Walsh                         "ffdc_list_file_path"]
1330bbd860fSMichael Walsh
1340bbd860fSMichael Walsh    plug_in_vars = parm_list + additional_values
1350bbd860fSMichael Walsh
1360bbd860fSMichael Walsh    for var_name in plug_in_vars:
1370bbd860fSMichael Walsh        var_value = BuiltIn().get_variable_value("${" + var_name + "}")
1380bbd860fSMichael Walsh        var_name = var_name.upper()
1390bbd860fSMichael Walsh        if var_value is None:
1400bbd860fSMichael Walsh            var_value = ""
1416741f740SMichael Walsh        os.environ["AUTOBOOT_" + var_name] = str(var_value)
1420bbd860fSMichael Walsh
1430bbd860fSMichael Walsh    if debug:
1446741f740SMichael Walsh        shell_rc, out_buf = \
1456741f740SMichael Walsh            gc.cmd_fnc_u("printenv | egrep AUTOBOOT_ | sort -u")
1460bbd860fSMichael Walsh
1470bbd860fSMichael Walsh###############################################################################
1480bbd860fSMichael Walsh
1490bbd860fSMichael Walsh
1500bbd860fSMichael Walsh###############################################################################
1516741f740SMichael Walshdef setup():
1520bbd860fSMichael Walsh
1530bbd860fSMichael Walsh    r"""
1546741f740SMichael Walsh    Do general program setup tasks.
1550bbd860fSMichael Walsh    """
1560bbd860fSMichael Walsh
1576741f740SMichael Walsh    global cp_setup_called
1580bbd860fSMichael Walsh
1596741f740SMichael Walsh    grp.rqprintn()
1606741f740SMichael Walsh
1616741f740SMichael Walsh    validate_parms()
1626741f740SMichael Walsh
1636741f740SMichael Walsh    grp.rqprint_pgm_header()
1646741f740SMichael Walsh
1656741f740SMichael Walsh    plug_in_setup()
1666741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
1676741f740SMichael Walsh        call_point='setup')
1686741f740SMichael Walsh    if rc != 0:
1696741f740SMichael Walsh        error_message = "Plug-in setup failed.\n"
1706741f740SMichael Walsh        grp.rprint_error_report(error_message)
1716741f740SMichael Walsh        BuiltIn().fail(error_message)
1726741f740SMichael Walsh    # Setting cp_setup_called lets our Teardown know that it needs to call
1736741f740SMichael Walsh    # the cleanup plug-in call point.
1746741f740SMichael Walsh    cp_setup_called = 1
1756741f740SMichael Walsh
1766741f740SMichael Walsh    # Keyword "FFDC" will fail if TEST_MESSAGE is not set.
1776741f740SMichael Walsh    BuiltIn().set_global_variable("${TEST_MESSAGE}", "${EMPTY}")
1786741f740SMichael Walsh
1796741f740SMichael Walsh    grp.rdprint_var(boot_table, 1)
1806741f740SMichael Walsh    grp.rdprint_var(boot_lists)
1810bbd860fSMichael Walsh
1820bbd860fSMichael Walsh###############################################################################
1830bbd860fSMichael Walsh
1840bbd860fSMichael Walsh
1850bbd860fSMichael Walsh###############################################################################
1866741f740SMichael Walshdef validate_parms():
1870bbd860fSMichael Walsh
1880bbd860fSMichael Walsh    r"""
1896741f740SMichael Walsh    Validate all program parameters.
1900bbd860fSMichael Walsh    """
1910bbd860fSMichael Walsh
1926741f740SMichael Walsh    grp.rqprintn()
1930bbd860fSMichael Walsh
1946741f740SMichael Walsh    grv.rvalid_value("openbmc_host")
1956741f740SMichael Walsh    grv.rvalid_value("openbmc_username")
1966741f740SMichael Walsh    grv.rvalid_value("openbmc_password")
1976741f740SMichael Walsh    if os_host != "":
1986741f740SMichael Walsh        grv.rvalid_value("os_username")
1996741f740SMichael Walsh        grv.rvalid_value("os_password")
2000bbd860fSMichael Walsh
2016741f740SMichael Walsh    if pdu_host != "":
2026741f740SMichael Walsh        grv.rvalid_value("pdu_username")
2036741f740SMichael Walsh        grv.rvalid_value("pdu_password")
2046741f740SMichael Walsh    grv.rvalid_integer("pdu_slot_no")
2056741f740SMichael Walsh    if openbmc_serial_host != "":
2066741f740SMichael Walsh        grv.rvalid_integer("openbmc_serial_port")
2076741f740SMichael Walsh    grv.rvalid_integer("max_num_tests")
2086741f740SMichael Walsh    grv.rvalid_value("openbmc_model")
2096741f740SMichael Walsh    grv.rvalid_integer("boot_pass")
2106741f740SMichael Walsh    grv.rvalid_integer("boot_fail")
2116741f740SMichael Walsh
2126741f740SMichael Walsh    plug_in_packages_list = grpi.rvalidate_plug_ins(plug_in_dir_paths)
2136741f740SMichael Walsh    BuiltIn().set_global_variable("${plug_in_packages_list}",
2146741f740SMichael Walsh                                  plug_in_packages_list)
2156741f740SMichael Walsh
2166741f740SMichael Walsh    if len(boot_list) == 0 and len(boot_stack) == 0:
2176741f740SMichael Walsh        error_message = "You must provide either a value for either the" +\
2186741f740SMichael Walsh            " boot_list or the boot_stack parm.\n"
2196741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
2206741f740SMichael Walsh
2216741f740SMichael Walsh    valid_boot_list(boot_list, valid_boot_types)
2226741f740SMichael Walsh    valid_boot_list(boot_stack, valid_boot_types)
2236741f740SMichael Walsh
2246741f740SMichael Walsh    return
2250bbd860fSMichael Walsh
2260bbd860fSMichael Walsh###############################################################################
2270bbd860fSMichael Walsh
2280bbd860fSMichael Walsh
2290bbd860fSMichael Walsh###############################################################################
2306741f740SMichael Walshdef my_get_state():
2310bbd860fSMichael Walsh
2320bbd860fSMichael Walsh    r"""
2336741f740SMichael Walsh    Get the system state plus a little bit of wrapping.
2340bbd860fSMichael Walsh    """
2350bbd860fSMichael Walsh
2366741f740SMichael Walsh    global state
2376741f740SMichael Walsh
2386741f740SMichael Walsh    req_states = ['epoch_seconds'] + st.default_req_states
2396741f740SMichael Walsh
2406741f740SMichael Walsh    grp.rqprint_timen("Getting system state.")
2416741f740SMichael Walsh    if test_mode:
2426741f740SMichael Walsh        state['epoch_seconds'] = int(time.time())
2436741f740SMichael Walsh    else:
2446741f740SMichael Walsh        state = st.get_state(req_states=req_states, quiet=0)
2456741f740SMichael Walsh    grp.rprint_var(state)
246341c21ebSMichael Walsh
247341c21ebSMichael Walsh###############################################################################
248341c21ebSMichael Walsh
249341c21ebSMichael Walsh
250341c21ebSMichael Walsh###############################################################################
2516741f740SMichael Walshdef select_boot():
252341c21ebSMichael Walsh
253341c21ebSMichael Walsh    r"""
254341c21ebSMichael Walsh    Select a boot test to be run based on our current state and return the
255341c21ebSMichael Walsh    chosen boot type.
256341c21ebSMichael Walsh
257341c21ebSMichael Walsh    Description of arguments:
2586741f740SMichael Walsh    state  The state of the machine.
259341c21ebSMichael Walsh    """
260341c21ebSMichael Walsh
26130dadae2SMichael Walsh    global boot_stack
26230dadae2SMichael Walsh
2636741f740SMichael Walsh    grp.rprint_timen("Selecting a boot test.")
2646741f740SMichael Walsh
2656741f740SMichael Walsh    my_get_state()
2666741f740SMichael Walsh
2676741f740SMichael Walsh    stack_popped = 0
2686741f740SMichael Walsh    if len(boot_stack) > 0:
2696741f740SMichael Walsh        stack_popped = 1
2706741f740SMichael Walsh        grp.rprint_dashes()
2716741f740SMichael Walsh        grp.rprint_var(boot_stack)
2726741f740SMichael Walsh        grp.rprint_dashes()
2736741f740SMichael Walsh        boot_candidate = boot_stack.pop()
2746741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
2756741f740SMichael Walsh            grp.rprint_timen("The machine state is valid for a '" +
2766741f740SMichael Walsh                             boot_candidate + "' boot test.")
2776741f740SMichael Walsh            grp.rprint_dashes()
2786741f740SMichael Walsh            grp.rprint_var(boot_stack)
2796741f740SMichael Walsh            grp.rprint_dashes()
2806741f740SMichael Walsh            return boot_candidate
281341c21ebSMichael Walsh        else:
2826741f740SMichael Walsh            grp.rprint_timen("The machine state is not valid for a '" +
2836741f740SMichael Walsh                             boot_candidate + "' boot test.")
2846741f740SMichael Walsh            boot_stack.append(boot_candidate)
2856741f740SMichael Walsh            popped_boot = boot_candidate
2866741f740SMichael Walsh
2876741f740SMichael Walsh    # Loop through your list selecting a boot_candidates
2886741f740SMichael Walsh    boot_candidates = []
2896741f740SMichael Walsh    for boot_candidate in boot_list:
2906741f740SMichael Walsh        if st.compare_states(state, boot_table[boot_candidate]['start']):
2916741f740SMichael Walsh            if stack_popped:
2926741f740SMichael Walsh                if st.compare_states(boot_table[boot_candidate]['end'],
2936741f740SMichael Walsh                   boot_table[popped_boot]['start']):
2946741f740SMichael Walsh                    boot_candidates.append(boot_candidate)
295341c21ebSMichael Walsh            else:
2966741f740SMichael Walsh                boot_candidates.append(boot_candidate)
2976741f740SMichael Walsh
2986741f740SMichael Walsh    if len(boot_candidates) == 0:
2996741f740SMichael Walsh        grp.rprint_timen("The user's boot list contained no boot tests" +
3006741f740SMichael Walsh                         " which are valid for the current machine state.")
3016741f740SMichael Walsh        boot_candidate = default_power_on
3026741f740SMichael Walsh        if not st.compare_states(state, boot_table[default_power_on]['start']):
3036741f740SMichael Walsh            boot_candidate = default_power_off
3046741f740SMichael Walsh        boot_candidates.append(boot_candidate)
3056741f740SMichael Walsh        grp.rprint_timen("Using default '" + boot_candidate +
3066741f740SMichael Walsh                         "' boot type to transtion to valid state.")
3076741f740SMichael Walsh
3086741f740SMichael Walsh    grp.rdprint_var(boot_candidates)
3096741f740SMichael Walsh
3106741f740SMichael Walsh    # Randomly select a boot from the candidate list.
3116741f740SMichael Walsh    boot = random.choice(boot_candidates)
312341c21ebSMichael Walsh
313341c21ebSMichael Walsh    return boot
3140bbd860fSMichael Walsh
3150bbd860fSMichael Walsh###############################################################################
31655302295SMichael Walsh
31755302295SMichael Walsh
31855302295SMichael Walsh###############################################################################
319341c21ebSMichael Walshdef print_last_boots():
320341c21ebSMichael Walsh
321341c21ebSMichael Walsh    r"""
322341c21ebSMichael Walsh    Print the last ten boots done with their time stamps.
323341c21ebSMichael Walsh    """
324341c21ebSMichael Walsh
325341c21ebSMichael Walsh    # indent 0, 90 chars wide, linefeed, char is "="
326341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
327341c21ebSMichael Walsh    grp.rqprintn("Last 10 boots:\n")
328341c21ebSMichael Walsh
329341c21ebSMichael Walsh    for boot_entry in last_ten:
330341c21ebSMichael Walsh        grp.rqprint(boot_entry)
331341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90)
332341c21ebSMichael Walsh
333341c21ebSMichael Walsh###############################################################################
334341c21ebSMichael Walsh
335341c21ebSMichael Walsh
336341c21ebSMichael Walsh###############################################################################
337341c21ebSMichael Walshdef print_defect_report():
338341c21ebSMichael Walsh
339341c21ebSMichael Walsh    r"""
340341c21ebSMichael Walsh    Print a defect report.
341341c21ebSMichael Walsh    """
342341c21ebSMichael Walsh
343341c21ebSMichael Walsh    grp.rqprintn()
344341c21ebSMichael Walsh    # indent=0, width=90, linefeed=1, char="="
345341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
346341c21ebSMichael Walsh    grp.rqprintn("Copy this data to the defect:\n")
347341c21ebSMichael Walsh
348341c21ebSMichael Walsh    grp.rqpvars(*parm_list)
349341c21ebSMichael Walsh
350341c21ebSMichael Walsh    grp.rqprintn()
351341c21ebSMichael Walsh
352341c21ebSMichael Walsh    print_last_boots()
353341c21ebSMichael Walsh    grp.rqprintn()
354341c21ebSMichael Walsh    grp.rqpvar(state)
355341c21ebSMichael Walsh
356341c21ebSMichael Walsh    # At some point I'd like to have the 'Call FFDC Methods' return a list
357341c21ebSMichael Walsh    # of files it has collected.  In that case, the following "ls" command
358341c21ebSMichael Walsh    # would no longer be needed.  For now, however, glob shows the files
359341c21ebSMichael Walsh    # named in FFDC_LIST_FILE_PATH so I will refrain from printing those
360341c21ebSMichael Walsh    # out (so we don't see duplicates in the list).
361341c21ebSMichael Walsh
362341c21ebSMichael Walsh    LOG_PREFIX = BuiltIn().get_variable_value("${LOG_PREFIX}")
363341c21ebSMichael Walsh
364341c21ebSMichael Walsh    output = '\n'.join(glob.glob(LOG_PREFIX + '*'))
365341c21ebSMichael Walsh    try:
3666741f740SMichael Walsh        ffdc_list = open(ffdc_list_file_path, 'r')
367341c21ebSMichael Walsh    except IOError:
368341c21ebSMichael Walsh        ffdc_list = ""
369341c21ebSMichael Walsh
370341c21ebSMichael Walsh    grp.rqprintn()
371341c21ebSMichael Walsh    grp.rqprintn("FFDC data files:")
372341c21ebSMichael Walsh    if status_file_path != "":
373341c21ebSMichael Walsh        grp.rqprintn(status_file_path)
374341c21ebSMichael Walsh
375341c21ebSMichael Walsh    grp.rqprintn(output)
376341c21ebSMichael Walsh    # grp.rqprintn(ffdc_list)
377341c21ebSMichael Walsh    grp.rqprintn()
378341c21ebSMichael Walsh
379341c21ebSMichael Walsh    grp.rqprint_dashes(0, 90, 1, "=")
380341c21ebSMichael Walsh
381341c21ebSMichael Walsh###############################################################################
3826741f740SMichael Walsh
3836741f740SMichael Walsh
3846741f740SMichael Walsh###############################################################################
3856741f740SMichael Walshdef my_ffdc():
3866741f740SMichael Walsh
3876741f740SMichael Walsh    r"""
3886741f740SMichael Walsh    Collect FFDC data.
3896741f740SMichael Walsh    """
3906741f740SMichael Walsh
3916741f740SMichael Walsh    global state
3926741f740SMichael Walsh
3936741f740SMichael Walsh    plug_in_setup()
3946741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
3956741f740SMichael Walsh        call_point='ffdc', stop_on_plug_in_failure=1)
3966741f740SMichael Walsh
3976741f740SMichael Walsh    AUTOBOOT_FFDC_PREFIX = os.environ['AUTOBOOT_FFDC_PREFIX']
3986741f740SMichael Walsh
3996741f740SMichael Walsh    # FFDC_LOG_PATH is used by "FFDC" keyword.
4006741f740SMichael Walsh    BuiltIn().set_global_variable("${FFDC_LOG_PATH}", ffdc_dir_path)
4016741f740SMichael Walsh
4026741f740SMichael Walsh    cmd_buf = ["FFDC", "ffdc_prefix=" + AUTOBOOT_FFDC_PREFIX]
4036741f740SMichael Walsh    grp.rpissuing_keyword(cmd_buf)
4046741f740SMichael Walsh    BuiltIn().run_keyword(*cmd_buf)
4056741f740SMichael Walsh
4066741f740SMichael Walsh    my_get_state()
4076741f740SMichael Walsh
4086741f740SMichael Walsh    print_defect_report()
4096741f740SMichael Walsh
4106741f740SMichael Walsh###############################################################################
4116741f740SMichael Walsh
4126741f740SMichael Walsh
4136741f740SMichael Walsh###############################################################################
4146741f740SMichael Walshdef print_test_start_message(boot_keyword):
4156741f740SMichael Walsh
4166741f740SMichael Walsh    r"""
4176741f740SMichael Walsh    Print a message indicating what boot test is about to run.
4186741f740SMichael Walsh
4196741f740SMichael Walsh    Description of arguments:
4206741f740SMichael Walsh    boot_keyword  The name of the boot which is to be run
4216741f740SMichael Walsh                  (e.g. "BMC Power On").
4226741f740SMichael Walsh    """
4236741f740SMichael Walsh
4246741f740SMichael Walsh    global last_ten
4256741f740SMichael Walsh
4266741f740SMichael Walsh    doing_msg = gp.sprint_timen("Doing \"" + boot_keyword + "\".")
4276741f740SMichael Walsh    grp.rqprint(doing_msg)
4286741f740SMichael Walsh
4296741f740SMichael Walsh    last_ten.append(doing_msg)
4306741f740SMichael Walsh
4316741f740SMichael Walsh    if len(last_ten) > 10:
4326741f740SMichael Walsh        del last_ten[0]
4336741f740SMichael Walsh
4346741f740SMichael Walsh###############################################################################
4356741f740SMichael Walsh
4366741f740SMichael Walsh
4376741f740SMichael Walsh###############################################################################
4386741f740SMichael Walshdef run_boot(boot):
4396741f740SMichael Walsh
4406741f740SMichael Walsh    r"""
4416741f740SMichael Walsh    Run the specified boot.
4426741f740SMichael Walsh
4436741f740SMichael Walsh    Description of arguments:
4446741f740SMichael Walsh    boot  The name of the boot test to be performed.
4456741f740SMichael Walsh    """
4466741f740SMichael Walsh
4476741f740SMichael Walsh    global state
4486741f740SMichael Walsh
4496741f740SMichael Walsh    print_test_start_message(boot)
4506741f740SMichael Walsh
4516741f740SMichael Walsh    plug_in_setup()
4526741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
4536741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="pre_boot")
4546741f740SMichael Walsh    if rc != 0:
4556741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
4566741f740SMichael Walsh            gp.sprint_var(rc, 1)
4576741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
4586741f740SMichael Walsh
4596741f740SMichael Walsh    if test_mode:
4606741f740SMichael Walsh        # In test mode, we'll pretend the boot worked by assigning its
4616741f740SMichael Walsh        # required end state to the default state value.
46230dadae2SMichael Walsh        state = st.strip_anchor_state(boot_table[boot]['end'])
4636741f740SMichael Walsh    else:
4646741f740SMichael Walsh        # Assertion:  We trust that the state data was made fresh by the
4656741f740SMichael Walsh        # caller.
4666741f740SMichael Walsh
4676741f740SMichael Walsh        grp.rprintn()
4686741f740SMichael Walsh
4696741f740SMichael Walsh        if boot_table[boot]['method_type'] == "keyword":
470*0b93fbf8SMichael Walsh            rk.my_run_keywords(boot_table[boot].get('lib_file_path', ''),
471*0b93fbf8SMichael Walsh                               boot_table[boot]['method'])
4726741f740SMichael Walsh
4736741f740SMichael Walsh        if boot_table[boot]['bmc_reboot']:
4746741f740SMichael Walsh            st.wait_for_comm_cycle(int(state['epoch_seconds']))
47530dadae2SMichael Walsh            plug_in_setup()
47630dadae2SMichael Walsh            rc, shell_rc, failed_plug_in_name = \
47730dadae2SMichael Walsh                grpi.rprocess_plug_in_packages(call_point="post_reboot")
47830dadae2SMichael Walsh            if rc != 0:
479*0b93fbf8SMichael Walsh                error_message = "Plug-in failed with non-zero return code.\n"
480*0b93fbf8SMichael Walsh                error_message += gp.sprint_var(rc, 1)
48130dadae2SMichael Walsh                BuiltIn().fail(gp.sprint_error(error_message))
4826741f740SMichael Walsh        else:
4836741f740SMichael Walsh            match_state = st.anchor_state(state)
4846741f740SMichael Walsh            del match_state['epoch_seconds']
4856741f740SMichael Walsh            # Wait for the state to change in any way.
4866741f740SMichael Walsh            st.wait_state(match_state, wait_time=state_change_timeout,
4876741f740SMichael Walsh                          interval="3 seconds", invert=1)
4886741f740SMichael Walsh
4896741f740SMichael Walsh        grp.rprintn()
4906741f740SMichael Walsh        if boot_table[boot]['end']['chassis'] == "Off":
4916741f740SMichael Walsh            boot_timeout = power_off_timeout
4926741f740SMichael Walsh        else:
4936741f740SMichael Walsh            boot_timeout = power_on_timeout
4946741f740SMichael Walsh        st.wait_state(boot_table[boot]['end'], wait_time=boot_timeout,
4956741f740SMichael Walsh                      interval="3 seconds")
4966741f740SMichael Walsh
4976741f740SMichael Walsh    plug_in_setup()
4986741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = \
4996741f740SMichael Walsh        grpi.rprocess_plug_in_packages(call_point="post_boot")
5006741f740SMichael Walsh    if rc != 0:
5016741f740SMichael Walsh        error_message = "Plug-in failed with non-zero return code.\n" +\
5026741f740SMichael Walsh            gp.sprint_var(rc, 1)
5036741f740SMichael Walsh        BuiltIn().fail(gp.sprint_error(error_message))
5046741f740SMichael Walsh
5056741f740SMichael Walsh###############################################################################
5066741f740SMichael Walsh
5076741f740SMichael Walsh
5086741f740SMichael Walsh###############################################################################
5096741f740SMichael Walshdef test_loop_body():
5106741f740SMichael Walsh
5116741f740SMichael Walsh    r"""
5126741f740SMichael Walsh    The main loop body for the loop in main_py.
5136741f740SMichael Walsh
5146741f740SMichael Walsh    Description of arguments:
5156741f740SMichael Walsh    boot_count  The iteration number (starts at 1).
5166741f740SMichael Walsh    """
5176741f740SMichael Walsh
5186741f740SMichael Walsh    global boot_count
5196741f740SMichael Walsh    global state
5206741f740SMichael Walsh    global next_boot
5216741f740SMichael Walsh    global boot_success
5226741f740SMichael Walsh
5236741f740SMichael Walsh    grp.rqprintn()
5246741f740SMichael Walsh
5256741f740SMichael Walsh    boot_count += 1
5266741f740SMichael Walsh
5276741f740SMichael Walsh    next_boot = select_boot()
5286741f740SMichael Walsh
5296741f740SMichael Walsh    grp.rqprint_timen("Starting boot " + str(boot_count) + ".")
5306741f740SMichael Walsh
5316741f740SMichael Walsh    # Clear the ffdc_list_file_path file.  Plug-ins may now write to it.
5326741f740SMichael Walsh    try:
5336741f740SMichael Walsh        os.remove(ffdc_list_file_path)
5346741f740SMichael Walsh    except OSError:
5356741f740SMichael Walsh        pass
5366741f740SMichael Walsh
5376741f740SMichael Walsh    cmd_buf = ["run_boot", next_boot]
5386741f740SMichael Walsh    boot_status, msg = BuiltIn().run_keyword_and_ignore_error(*cmd_buf)
5396741f740SMichael Walsh    if boot_status == "FAIL":
5406741f740SMichael Walsh        grp.rprint(msg)
5416741f740SMichael Walsh
5426741f740SMichael Walsh    grp.rqprintn()
5436741f740SMichael Walsh    if boot_status == "PASS":
5446741f740SMichael Walsh        boot_success = 1
5456741f740SMichael Walsh        grp.rqprint_timen("BOOT_SUCCESS: \"" + next_boot + "\" succeeded.")
5466741f740SMichael Walsh    else:
5476741f740SMichael Walsh        boot_success = 0
5486741f740SMichael Walsh        grp.rqprint_timen("BOOT_FAILED: \"" + next_boot + "\" failed.")
5496741f740SMichael Walsh
5506741f740SMichael Walsh    boot_results.update(next_boot, boot_status)
5516741f740SMichael Walsh
5526741f740SMichael Walsh    plug_in_setup()
5536741f740SMichael Walsh    # NOTE: A post_test_case call point failure is NOT counted as a boot
5546741f740SMichael Walsh    # failure.
5556741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5566741f740SMichael Walsh        call_point='post_test_case', stop_on_plug_in_failure=1)
5576741f740SMichael Walsh
5586741f740SMichael Walsh    plug_in_setup()
5596741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5606741f740SMichael Walsh        call_point='ffdc_check', shell_rc=0x00000200,
5616741f740SMichael Walsh        stop_on_plug_in_failure=1, stop_on_non_zero_rc=1)
5626741f740SMichael Walsh    if boot_status != "PASS" or ffdc_check == "All" or shell_rc == 0x00000200:
5636741f740SMichael Walsh        cmd_buf = ["my_ffdc"]
5646741f740SMichael Walsh        grp.rpissuing_keyword(cmd_buf)
5656741f740SMichael Walsh        BuiltIn().run_keyword_and_continue_on_failure(*cmd_buf)
5666741f740SMichael Walsh
5676741f740SMichael Walsh    plug_in_setup()
5686741f740SMichael Walsh    rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5696741f740SMichael Walsh        call_point='stop_check')
5706741f740SMichael Walsh    if rc != 0:
5716741f740SMichael Walsh        error_message = "Stopping as requested by user.\n"
5726741f740SMichael Walsh        grp.rprint_error_report(error_message)
5736741f740SMichael Walsh        BuiltIn().fail(error_message)
5746741f740SMichael Walsh
5756741f740SMichael Walsh    boot_results.print_report()
5766741f740SMichael Walsh    grp.rqprint_timen("Finished boot " + str(boot_count) + ".")
5776741f740SMichael Walsh
5786741f740SMichael Walsh    return True
5796741f740SMichael Walsh
5806741f740SMichael Walsh###############################################################################
5816741f740SMichael Walsh
5826741f740SMichael Walsh
5836741f740SMichael Walsh###############################################################################
5846741f740SMichael Walshdef program_teardown():
5856741f740SMichael Walsh
5866741f740SMichael Walsh    r"""
5876741f740SMichael Walsh    Clean up after this program.
5886741f740SMichael Walsh    """
5896741f740SMichael Walsh
5906741f740SMichael Walsh    if cp_setup_called:
5916741f740SMichael Walsh        plug_in_setup()
5926741f740SMichael Walsh        rc, shell_rc, failed_plug_in_name = grpi.rprocess_plug_in_packages(
5936741f740SMichael Walsh            call_point='cleanup', stop_on_plug_in_failure=1)
5946741f740SMichael Walsh
595*0b93fbf8SMichael Walsh    # Save boot_results object to a file in case it is needed again.
596*0b93fbf8SMichael Walsh    grp.rprint_timen("Saving boot_results to the following path.")
597*0b93fbf8SMichael Walsh    grp.rprint_var(boot_results_file_path)
598*0b93fbf8SMichael Walsh    pickle.dump(boot_results, open(boot_results_file_path, 'wb'),
599*0b93fbf8SMichael Walsh                pickle.HIGHEST_PROTOCOL)
600*0b93fbf8SMichael Walsh
6016741f740SMichael Walsh###############################################################################
6026741f740SMichael Walsh
6036741f740SMichael Walsh
6046741f740SMichael Walsh###############################################################################
6056741f740SMichael Walshdef main_py():
6066741f740SMichael Walsh
6076741f740SMichael Walsh    r"""
6086741f740SMichael Walsh    Do main program processing.
6096741f740SMichael Walsh    """
6106741f740SMichael Walsh
6116741f740SMichael Walsh    setup()
6126741f740SMichael Walsh
6136741f740SMichael Walsh    # Process caller's boot_stack.
6146741f740SMichael Walsh    while (len(boot_stack) > 0):
6156741f740SMichael Walsh        test_loop_body()
6166741f740SMichael Walsh
61730dadae2SMichael Walsh    grp.rprint_timen("Finished processing stack.")
61830dadae2SMichael Walsh
6196741f740SMichael Walsh    # Process caller's boot_list.
6206741f740SMichael Walsh    if len(boot_list) > 0:
6216741f740SMichael Walsh        for ix in range(1, max_num_tests + 1):
6226741f740SMichael Walsh            test_loop_body()
6236741f740SMichael Walsh
6246741f740SMichael Walsh    grp.rqprint_timen("Completed all requested boot tests.")
6256741f740SMichael Walsh
6266741f740SMichael Walsh###############################################################################
627