1#!/usr/bin/env python3
2
3r"""
4Check for stop conditions.  Return code of 2 if stop conditions are found.
5"""
6
7import argparse
8import os
9import re
10
11from gen_arg import *  # NOQA
12from gen_call_robot import *  # NOQA
13from gen_cmd import *  # NOQA
14from gen_misc import *  # NOQA
15from gen_plug_in_utils import *  # NOQA
16from gen_print import *  # NOQA
17from gen_valid import *  # NOQA
18
19# Set exit_on_error for gen_valid functions.
20set_exit_on_error(True)
21
22# Initialize default plug-in parms..
23STOP_REST_FAIL = 0
24STOP_COMMAND = ""
25stop_test_rc = 2
26STOP_VERIFY_HARDWARE_FAIL = 0
27
28
29# Create parser object to process command line parameters and args.
30parser = argparse.ArgumentParser(
31    usage="%(prog)s [OPTIONS]",
32    description='If the "Stop" plug-in is selected by the user, %(prog)s'
33    + " is called by OBMC Boot Test after each boot test.  If %(prog)s returns"
34    + " "
35    + str(stop_test_rc)
36    + ", then OBMC Boot Test will stop.  The user"
37    + " may set environment variable STOP_COMMAND to contain any valid bash"
38    + " command or program.  %(prog)s will run this stop command.  If the stop"
39    + " command returns non-zero, then %(prog)s will return "
40    + str(stop_test_rc)
41    + ".  %(prog)s recognizes some special values for"
42    + ' STOP_COMMAND: 1) "FAIL" means that OBMC Boot Test should stop'
43    + ' whenever a boot test fails. 2) "ALL" means that OBMC Boot Test'
44    + " should stop after any boot test.  If environment variable"
45    + " STOP_REST_FAIL is set, OBMC Boot Test will stop if REST commands are"
46    + " no longer working.",
47    formatter_class=argparse.ArgumentDefaultsHelpFormatter,
48    prefix_chars="-+",
49)
50
51# The stock_list will be passed to gen_get_options.  We populate it with the names of stock parm options we
52# want.  These stock parms are pre-defined by gen_get_options.
53stock_list = [
54    ("test_mode", get_plug_default("test_mode", 0)),
55    ("quiet", get_plug_default("quiet", 0)),
56    ("debug", get_plug_default("debug", 0)),
57]
58
59
60def exit_function(signal_number=0, frame=None):
61    r"""
62    Execute whenever the program ends normally or with the signals that we catch (i.e. TERM, INT).
63
64    This function will be called by gen_exit_function().
65    """
66
67    process_robot_output_files()
68
69
70def validate_parms():
71    r"""
72    Validate program parameters, etc.
73
74    This function will be called by gen_setup().
75    """
76
77    get_plug_vars()
78
79
80def stop_check():
81    r"""
82    Stop this program with the stop check return code.
83    """
84
85    if MASTER_PID != PROGRAM_PID:
86        save_plug_in_value(stop_check_rc=stop_test_rc)
87    exit(stop_test_rc)
88
89
90def rest_fail():
91    r"""
92    If STOP_REST_FAIL, then this function will determine whether REST commands to the target are working.  If
93    not, this function will stop the program by returning stop_test_rc.
94    """
95
96    if not STOP_REST_FAIL:
97        return
98
99    REDFISH_SUPPORT_TRANS_STATE = int(
100        os.environ.get("REDFISH_SUPPORT_TRANS_STATE", 0)
101    ) or int(os.environ.get("AUTOBOOT_REDFISH_SUPPORT_TRANS_STATE", 0))
102
103    if REDFISH_SUPPORT_TRANS_STATE:
104        interface = "redfish"
105    else:
106        interface = "rest"
107
108    print_timen("Checking to see whether %s commands are working." % interface)
109    init_robot_out_parms(get_plug_in_package_name() + "." + pgm_name + ".")
110    lib_file_path = (
111        init_robot_file_path("lib/utils.robot")
112        + ":"
113        + init_robot_file_path("lib/gen_robot_print.py")
114    )
115    set_mod_global(lib_file_path)
116    timeout = "0 seconds"
117    interval = "1 second"
118    keyword_string = (
119        "${match_state}=  Create Dictionary  %s=1 ;" % interface
120        + " ${state}=  Wait State  ${match_state}  "
121        + timeout
122        + "  "
123        + interval
124        + "  quiet=${1} ; Rpvar  state"
125    )
126    set_mod_global(keyword_string)
127    cmd_buf = create_robot_cmd_string(
128        "extended/run_keyword.robot",
129        OPENBMC_HOST,
130        SSH_PORT,
131        HTTPS_PORT,
132        OPENBMC_USERNAME,
133        OPENBMC_PASSWORD,
134        REDFISH_SUPPORT_TRANS_STATE,
135        keyword_string,
136        lib_file_path,
137        quiet,
138        test_mode,
139        debug,
140        outputdir,
141        output,
142        log,
143        report,
144        loglevel,
145    )
146    if not robot_cmd_fnc(cmd_buf):
147        print_timen(
148            "The caller wishes to stop test execution if %s commands are"
149            " failing." % interface
150        )
151        stop_check()
152    print_timen(
153        "%s commands are working so no reason as of yet to stop the test."
154        % interface
155    )
156
157
158def esel_stop_check():
159    r"""
160    Run the esel_stop_check program to determine whether any eSEL entries found warrant stopping the test
161    run.  See esel_stop_check help text for details.
162    """
163
164    if STOP_ESEL_STOP_FILE_PATH == "":
165        return
166
167    cmd_buf = (
168        "esel_stop_check --esel_stop_file_path=" + STOP_ESEL_STOP_FILE_PATH
169    )
170    shell_rc, out_buf = shell_cmd(cmd_buf, show_err=0)
171    if shell_rc == stop_test_rc:
172        print_timen(
173            "The caller wishes to stop test execution based on the presence of"
174            " certain esel entries."
175        )
176        stop_check()
177
178
179def pel_stop_check():
180    r"""
181    Determine whether any PEL entries found warrant stopping the test
182    run.
183    """
184
185    if STOP_PEL_STOP_FILE_PATH == "":
186        return
187
188    pel_txt_file_path = (
189        os.environ.get("AUTOBOOT_FFDC_DIR_PATH", "")
190        + os.environ.get("AUTOBOOT_FFDC_PREFIX", "")
191        + "PEL_logs_list.json"
192    )
193
194    if not os.path.isfile(pel_txt_file_path):
195        qprint_timen(
196            "The following file was not present so no further"
197            + " action will be taken."
198        )
199        qprint_var(pel_txt_file_path)
200        return
201
202    default_stop_dir_path = ""
203
204    # If pel_stop_file_path is unqualified and cannot be found, pre-pend
205    # default_stop_dir_path for the user.
206    pel_stop_file_path = os.environ.get("STOP_PEL_STOP_FILE_PATH", "")
207    if not os.path.isfile(pel_stop_file_path) and os.path.isfile(
208        default_stop_dir_path + pel_stop_file_path
209    ):
210        pel_stop_file_path = default_stop_dir_path + pel_stop_file_path
211        qprint_timen("Using default stop file path.")
212        qprint_var(pel_stop_file_path)
213
214    # First, read the file in and convert it to a list.
215    pel_stop_list = file_to_list(pel_stop_file_path, newlines=0, comments=0)
216
217    if len(pel_stop_list) == 0:
218        print_timen(
219            "There are no records to process in " + pel_stop_file_path + "."
220        )
221        return
222
223    pel_all_list = file_to_list(pel_txt_file_path, newlines=0, comments=0)
224
225    if len(pel_all_list) == 0:
226        print_timen(
227            "There are no records to process in " + pel_txt_file_path + "."
228        )
229        return
230
231    for stop_pel in pel_stop_list:
232        for pel_all in pel_all_list:
233            pel_match = re.search(".*SRC.*" + stop_pel + ".*", pel_all)
234            if pel_match:
235                print_timen(
236                    "The caller wishes to stop test execution based on "
237                    + "the presence of certain PEL entries."
238                )
239                stop_check()
240
241
242def main():
243    gen_setup()
244
245    print_plug_in_header()
246
247    if STOP_COMMAND.upper() == "FAIL":
248        if AUTOBOOT_BOOT_SUCCESS == "0":
249            print_timen("The caller wishes to stop after each boot failure.")
250            stop_check()
251    elif STOP_COMMAND.upper() == "ALL":
252        print_timen("The caller wishes to stop after each boot test.")
253        stop_check()
254    elif len(STOP_COMMAND) > 0:
255        shell_rc, out_buf = shell_cmd(STOP_COMMAND, quiet=quiet, show_err=0)
256        if shell_rc != 0:
257            print_timen("The caller wishes to stop test execution.")
258            stop_check()
259
260    rest_fail()
261
262    esel_stop_check()
263
264    pel_stop_check()
265
266    if STOP_VERIFY_HARDWARE_FAIL:
267        hardware_error_found = restore_plug_in_value(0, "Verify_hardware")
268        if hardware_error_found:
269            print_timen(
270                "The caller wishes to stop test execution when the"
271                " Verify_hardware plug-in detects a hardware error."
272            )
273            stop_check()
274
275    qprint_timen("The caller does not wish to stop the test run.")
276
277
278main()
279