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        REST_USERNAME,
133        REST_PASSWORD,
134        OPENBMC_USERNAME,
135        OPENBMC_PASSWORD,
136        REDFISH_SUPPORT_TRANS_STATE,
137        keyword_string,
138        lib_file_path,
139        quiet,
140        test_mode,
141        debug,
142        outputdir,
143        output,
144        log,
145        report,
146        loglevel,
147    )
148    if not robot_cmd_fnc(cmd_buf):
149        print_timen(
150            "The caller wishes to stop test execution if %s commands are"
151            " failing." % interface
152        )
153        stop_check()
154    print_timen(
155        "%s commands are working so no reason as of yet to stop the test."
156        % interface
157    )
158
159
160def esel_stop_check():
161    r"""
162    Run the esel_stop_check program to determine whether any eSEL entries found warrant stopping the test
163    run.  See esel_stop_check help text for details.
164    """
165
166    if STOP_ESEL_STOP_FILE_PATH == "":
167        return
168
169    cmd_buf = (
170        "esel_stop_check --esel_stop_file_path=" + STOP_ESEL_STOP_FILE_PATH
171    )
172    shell_rc, out_buf = shell_cmd(cmd_buf, show_err=0)
173    if shell_rc == stop_test_rc:
174        print_timen(
175            "The caller wishes to stop test execution based on the presence of"
176            " certain esel entries."
177        )
178        stop_check()
179
180
181def pel_stop_check():
182    r"""
183    Determine whether any PEL entries found warrant stopping the test
184    run.
185    """
186
187    if STOP_PEL_STOP_FILE_PATH == "":
188        return
189
190    pel_txt_file_path = (
191        os.environ.get("AUTOBOOT_FFDC_DIR_PATH", "")
192        + os.environ.get("AUTOBOOT_FFDC_PREFIX", "")
193        + "PEL_logs_list.json"
194    )
195
196    if not os.path.isfile(pel_txt_file_path):
197        qprint_timen(
198            "The following file was not present so no further"
199            + " action will be taken."
200        )
201        qprint_var(pel_txt_file_path)
202        return
203
204    default_stop_dir_path = "/afs/rchland.ibm.com/projects/esw/dvt/"
205
206    # If pel_stop_file_path is unqualified and cannot be found, pre-pend
207    # default_stop_dir_path for the user.
208    pel_stop_file_path = os.environ.get("STOP_PEL_STOP_FILE_PATH", "")
209    if not os.path.isfile(pel_stop_file_path) and os.path.isfile(
210        default_stop_dir_path + pel_stop_file_path
211    ):
212        pel_stop_file_path = default_stop_dir_path + pel_stop_file_path
213        qprint_timen("Using default stop file path.")
214        qprint_var(pel_stop_file_path)
215
216    # First, read the file in and convert it to a list.
217    pel_stop_list = file_to_list(pel_stop_file_path, newlines=0, comments=0)
218
219    if len(pel_stop_list) == 0:
220        print_timen(
221            "There are no records to process in " + pel_stop_file_path + "."
222        )
223        return
224
225    pel_all_list = file_to_list(pel_txt_file_path, newlines=0, comments=0)
226
227    if len(pel_all_list) == 0:
228        print_timen(
229            "There are no records to process in " + pel_txt_file_path + "."
230        )
231        return
232
233    for stop_pel in pel_stop_list:
234        for pel_all in pel_all_list:
235            pel_match = re.search(".*SRC.*" + stop_pel + ".*", pel_all)
236            if pel_match:
237                print_timen(
238                    "The caller wishes to stop test execution based on "
239                    + "the presence of certain PEL entries."
240                )
241                stop_check()
242
243
244def main():
245    gen_setup()
246
247    print_plug_in_header()
248
249    if STOP_COMMAND.upper() == "FAIL":
250        if AUTOBOOT_BOOT_SUCCESS == "0":
251            print_timen("The caller wishes to stop after each boot failure.")
252            stop_check()
253    elif STOP_COMMAND.upper() == "ALL":
254        print_timen("The caller wishes to stop after each boot test.")
255        stop_check()
256    elif len(STOP_COMMAND) > 0:
257        shell_rc, out_buf = shell_cmd(STOP_COMMAND, quiet=quiet, show_err=0)
258        if shell_rc != 0:
259            print_timen("The caller wishes to stop test execution.")
260            stop_check()
261
262    rest_fail()
263
264    esel_stop_check()
265
266    pel_stop_check()
267
268    if STOP_VERIFY_HARDWARE_FAIL:
269        hardware_error_found = restore_plug_in_value(0, "Verify_hardware")
270        if hardware_error_found:
271            print_timen(
272                "The caller wishes to stop test execution when the"
273                " Verify_hardware plug-in detects a hardware error."
274            )
275            stop_check()
276
277    qprint_timen("The caller does not wish to stop the test run.")
278
279
280main()
281