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