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