blob: 1088cb5660d21891febb7a1e03349f1a5d2de793 [file] [log] [blame]
Michael Walshffee58a2016-11-22 11:28:33 -06001#!/usr/bin/env python
2
3r"""
4This module provides functions which are useful for running plug-ins from a
5robot program.
6"""
7
8import sys
9import subprocess
10from robot.libraries.BuiltIn import BuiltIn
Michael Walshffee58a2016-11-22 11:28:33 -060011import os
12import tempfile
13
14import gen_print as gp
Michael Walshffee58a2016-11-22 11:28:33 -060015import gen_misc as gm
Michael Walsh957a2b22017-05-30 17:56:13 -050016import gen_cmd as gc
Michael Walshffee58a2016-11-22 11:28:33 -060017
18
Michael Walshffee58a2016-11-22 11:28:33 -060019def rvalidate_plug_ins(plug_in_dir_paths,
20 quiet=1):
Michael Walshffee58a2016-11-22 11:28:33 -060021 r"""
22 Call the external validate_plug_ins.py program which validates the plug-in
23 dir paths given to it. Return a list containing a normalized path for
24 each plug-in selected.
25
26 Description of arguments:
27 plug_in_dir_paths A colon-separated list of plug-in
28 directory paths.
29 quiet If quiet is set to 1, this function will
30 NOT write status messages to stdout.
31 """
32
33 cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
George Keishing36efbc02018-12-12 10:18:23 -060034 rc, out_buf = gc.shell_cmd(cmd_buf, print_output=0)
Michael Walshffee58a2016-11-22 11:28:33 -060035 if rc != 0:
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050036 BuiltIn().fail(gp.sprint_error("Validate plug ins call failed. See"
37 + " stderr text for details.\n"))
Michael Walshffee58a2016-11-22 11:28:33 -060038
George Keishing36efbc02018-12-12 10:18:23 -060039 # plug_in_packages_list = out_buf.split("\n")
40 plug_in_packages_list = list(filter(None, out_buf.split("\n")))
Michael Walshffee58a2016-11-22 11:28:33 -060041 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
42 return []
43
44 return plug_in_packages_list
45
Michael Walshffee58a2016-11-22 11:28:33 -060046
Michael Walshffee58a2016-11-22 11:28:33 -060047def rprocess_plug_in_packages(plug_in_packages_list=None,
48 call_point="setup",
49 shell_rc="0x00000000",
50 stop_on_plug_in_failure=1,
51 stop_on_non_zero_rc=0,
52 release_type="obmc",
53 quiet=None,
Michael Walshfa74bbb2018-10-30 13:21:03 -050054 debug=None,
55 return_history=False):
Michael Walshffee58a2016-11-22 11:28:33 -060056 r"""
57 Call the external process_plug_in_packages.py to process the plug-in
58 packages. Return the following:
59 rc The return code - 0 = PASS, 1 = FAIL.
60 shell_rc The shell return code returned by
61 process_plug_in_packages.py.
62 failed_plug_in_name The failed plug in name (if any).
63
64 Description of arguments:
65 plug_in_packages_list A python list of plug-in directory paths.
66 call_point The call point program to be called for
67 each plug-in package (e.g. post_boot).
68 This name should not include the "cp_"
69 prefix.
70 shell_rc The user may supply a value other than
71 zero to indicate an acceptable non-zero
72 return code. For example, if this value
73 equals 0x00000200, it means that for each
74 plug-in call point that runs, a 0x00000200
75 will not be counted as a failure.
76 stop_on_plug_in_failure If this parameter is set to 1, this
77 program will stop and return non-zero if
78 the call point program from any plug-in
79 directory fails. Conversely, if it is set
80 to false, this program will run the call
81 point program from each and every plug-in
82 directory regardless of their return
83 values. Typical example cases where you'd
84 want to run all plug-in call points
85 regardless of success or failure would be
86 "cleanup" or "ffdc" call points.
87 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
88 call point program returns a valid
89 non-zero return code (see "shell_rc" parm
90 above), this program will stop processing
91 and return 0 (success). Since this
92 constitutes a successful exit, this would
93 normally be used where the caller wishes
94 to stop processing if one of the plug-in
95 directory call point programs returns a
96 special value indicating that some special
97 case has been found. An example might be
98 in calling some kind of "check_errl" call
99 point program. Such a call point program
100 might return a 2 (i.e. 0x00000200) to
101 indicate that a given error log entry was
102 found in an "ignore" list and is therefore
103 to be ignored. That being the case, no
104 other "check_errl" call point program
105 would need to be called.
106 release_type The type of release being tested (e.g.
107 "obmc", "op", "fips"). This influences
108 which integrated plug-ins are selected.
109 quiet If quiet is set to 1, this function will
110 NOT write status messages to stdout. This
111 will default to the global quiet program
112 parm or to 0.
113 debug If this parameter is set to 1, this
114 function will print additional debug
115 information. This is mainly to be used by
116 the developer of this function. This will
117 default to the global quiet program parm
118 or to 0.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500119 return_history In addition to rc, shell_rc and
120 failed_plug_in_name, return a list
121 containing historical output that looks
122 like the following:
123
124 history:
125 history[0]: #(CDT) 2018/10/30 12:25:49 - Running
126 OBMC_Sample/cp_post_stack
Michael Walshffee58a2016-11-22 11:28:33 -0600127 """
128
129 rc = 0
130
Michael Walshfa74bbb2018-10-30 13:21:03 -0500131 plug_in_packages_list = gp.get_var_value(plug_in_packages_list, [])
Michael Walshffee58a2016-11-22 11:28:33 -0600132
133 # If there are no plug-in packages to process, return successfully.
134 if len(plug_in_packages_list) == 0:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500135 if return_history:
136 return 0, 0, "", []
137 else:
138 return 0, 0, ""
Michael Walshffee58a2016-11-22 11:28:33 -0600139
Michael Walshfa74bbb2018-10-30 13:21:03 -0500140 quiet = int(gp.get_var_value(quiet, 0))
141 debug = int(gp.get_var_value(debug, 0))
Michael Walshffee58a2016-11-22 11:28:33 -0600142
143 # Create string from list.
144 plug_in_dir_paths = ':'.join(plug_in_packages_list)
145
146 temp = tempfile.NamedTemporaryFile()
147 temp_file_path = temp.name
148 temp2 = tempfile.NamedTemporaryFile()
149 temp_properties_file_path = temp2.name
150
Michael Walshfa74bbb2018-10-30 13:21:03 -0500151 if debug:
Michael Walshffee58a2016-11-22 11:28:33 -0600152 os.environ["PERF_TRACE"] = "1"
153 debug_string = " --quiet=0"
154 else:
155 debug_string = ""
156
157 loc_shell_rc = 0
158
159 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500160 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600161 str(shell_rc) + " --stop_on_plug_in_failure=" +\
162 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
163 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
Michael Walshfa74bbb2018-10-30 13:21:03 -0500164 if quiet:
Michael Walshffee58a2016-11-22 11:28:33 -0600165 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
166 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600167 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
168 temp_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500169 if debug:
170 gp.print_issuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600171 else:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500172 gp.print_timen("Processing " + call_point
173 + " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600174
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500175 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True,
176 executable='/bin/bash')
Michael Walshffee58a2016-11-22 11:28:33 -0600177
Michael Walshfa74bbb2018-10-30 13:21:03 -0500178 if return_history:
179 # Get the "Running" statements from the output.
180 regex = " Running [^/]+/cp_"
181 cmd_buf = "egrep '" + regex + "' " + temp_file_path
182 _, history = gc.shell_cmd(cmd_buf, quiet=(not debug), print_output=0,
183 show_err=0, ignore_err=1)
184 history = [x + "\n" for x in filter(None, history.split("\n"))]
185 else:
186 history = []
187
Michael Walshffee58a2016-11-22 11:28:33 -0600188 # As process_plug_in_packages.py help text states, it will print the
189 # values of failed_plug_in_name and shell_rc in the following format:
190 # failed_plug_in_name: <failed plug-in value, if any>
191 # shell_rc: <shell return code value of last
192 # call point program>
193
194 # We want to obtain those values from the output. To make the task
195 # simpler, we'll start by grepping the output for lines that might fit
196 # such a format:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500197 # A valid bash variable against the left margin followed by...
198 # - A colon followed by...
Michael Walshffee58a2016-11-22 11:28:33 -0600199 # - Zero or more spaces
Michael Walsh957a2b22017-05-30 17:56:13 -0500200 bash_var_regex = "[_[:alpha:]][_[:alnum:]]*"
201 regex = "^" + bash_var_regex + ":[ ]*"
202 cmd_buf = "egrep '" + regex + "' " + temp_file_path + " > " +\
203 temp_properties_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500204 gp.dprint_issuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500205 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600206
207 # Next we call my_parm_file to create a properties dictionary.
208 properties = gm.my_parm_file(temp_properties_file_path)
209
210 # Finally, we access the 2 values that we need.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500211 shell_rc = int(properties.get('shell_rc', '0x0000000000000000'), 16)
212 failed_plug_in_name = properties.get('failed_plug_in_name', '')
Michael Walshffee58a2016-11-22 11:28:33 -0600213
Michael Walsh957a2b22017-05-30 17:56:13 -0500214 if proc_plug_pkg_rc != 0:
Michael Walsh0a3bdb42019-01-31 16:21:44 +0000215 if quiet:
216 os.system("cat " + temp_file_path + " >&2")
Michael Walshfa74bbb2018-10-30 13:21:03 -0500217 if grep_rc != 0:
Michael Walsh0d5f96a2019-05-20 10:09:57 -0500218 gp.print_var(grep_rc, gp.hexa())
219 gp.print_var(proc_plug_pkg_rc, gp.hexa())
Michael Walshfa74bbb2018-10-30 13:21:03 -0500220 gp.print_timen("Re-cap of plug-in failures:")
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500221 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' "
Michael Walshfa74bbb2018-10-30 13:21:03 -0500222 + temp_properties_file_path + " | egrep -v '^\\--'",
223 quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600224 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600225
Michael Walshfa74bbb2018-10-30 13:21:03 -0500226 if return_history:
227 return rc, shell_rc, failed_plug_in_name, history
228 else:
229 return rc, shell_rc, failed_plug_in_name