blob: 5c1dd06414b2c1b4c18152b1f96af4142a58bd61 [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
11import commands
12import os
13import tempfile
14
15import gen_print as gp
Michael Walshffee58a2016-11-22 11:28:33 -060016import gen_misc as gm
Michael Walsh957a2b22017-05-30 17:56:13 -050017import gen_cmd as gc
Michael Walshffee58a2016-11-22 11:28:33 -060018
19
Michael Walshffee58a2016-11-22 11:28:33 -060020def rvalidate_plug_ins(plug_in_dir_paths,
21 quiet=1):
Michael Walshffee58a2016-11-22 11:28:33 -060022 r"""
23 Call the external validate_plug_ins.py program which validates the plug-in
24 dir paths given to it. Return a list containing a normalized path for
25 each plug-in selected.
26
27 Description of arguments:
28 plug_in_dir_paths A colon-separated list of plug-in
29 directory paths.
30 quiet If quiet is set to 1, this function will
31 NOT write status messages to stdout.
32 """
33
34 cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
35 if int(quiet) != 1:
Michael Walshfa74bbb2018-10-30 13:21:03 -050036 gp.print_issuing(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -060037 rc, out_buf = commands.getstatusoutput(cmd_buf)
38 if rc != 0:
39 message = gp.sprint_varx("rc", rc, 1) + out_buf
Michael Walshfa74bbb2018-10-30 13:21:03 -050040 gp.printn(out_buf, 'STDERR')
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050041 BuiltIn().fail(gp.sprint_error("Validate plug ins call failed. See"
42 + " stderr text for details.\n"))
Michael Walshffee58a2016-11-22 11:28:33 -060043
44 plug_in_packages_list = out_buf.split("\n")
45 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
46 return []
47
48 return plug_in_packages_list
49
Michael Walshffee58a2016-11-22 11:28:33 -060050
Michael Walshffee58a2016-11-22 11:28:33 -060051def rprocess_plug_in_packages(plug_in_packages_list=None,
52 call_point="setup",
53 shell_rc="0x00000000",
54 stop_on_plug_in_failure=1,
55 stop_on_non_zero_rc=0,
56 release_type="obmc",
57 quiet=None,
Michael Walshfa74bbb2018-10-30 13:21:03 -050058 debug=None,
59 return_history=False):
Michael Walshffee58a2016-11-22 11:28:33 -060060 r"""
61 Call the external process_plug_in_packages.py to process the plug-in
62 packages. Return the following:
63 rc The return code - 0 = PASS, 1 = FAIL.
64 shell_rc The shell return code returned by
65 process_plug_in_packages.py.
66 failed_plug_in_name The failed plug in name (if any).
67
68 Description of arguments:
69 plug_in_packages_list A python list of plug-in directory paths.
70 call_point The call point program to be called for
71 each plug-in package (e.g. post_boot).
72 This name should not include the "cp_"
73 prefix.
74 shell_rc The user may supply a value other than
75 zero to indicate an acceptable non-zero
76 return code. For example, if this value
77 equals 0x00000200, it means that for each
78 plug-in call point that runs, a 0x00000200
79 will not be counted as a failure.
80 stop_on_plug_in_failure If this parameter is set to 1, this
81 program will stop and return non-zero if
82 the call point program from any plug-in
83 directory fails. Conversely, if it is set
84 to false, this program will run the call
85 point program from each and every plug-in
86 directory regardless of their return
87 values. Typical example cases where you'd
88 want to run all plug-in call points
89 regardless of success or failure would be
90 "cleanup" or "ffdc" call points.
91 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
92 call point program returns a valid
93 non-zero return code (see "shell_rc" parm
94 above), this program will stop processing
95 and return 0 (success). Since this
96 constitutes a successful exit, this would
97 normally be used where the caller wishes
98 to stop processing if one of the plug-in
99 directory call point programs returns a
100 special value indicating that some special
101 case has been found. An example might be
102 in calling some kind of "check_errl" call
103 point program. Such a call point program
104 might return a 2 (i.e. 0x00000200) to
105 indicate that a given error log entry was
106 found in an "ignore" list and is therefore
107 to be ignored. That being the case, no
108 other "check_errl" call point program
109 would need to be called.
110 release_type The type of release being tested (e.g.
111 "obmc", "op", "fips"). This influences
112 which integrated plug-ins are selected.
113 quiet If quiet is set to 1, this function will
114 NOT write status messages to stdout. This
115 will default to the global quiet program
116 parm or to 0.
117 debug If this parameter is set to 1, this
118 function will print additional debug
119 information. This is mainly to be used by
120 the developer of this function. This will
121 default to the global quiet program parm
122 or to 0.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500123 return_history In addition to rc, shell_rc and
124 failed_plug_in_name, return a list
125 containing historical output that looks
126 like the following:
127
128 history:
129 history[0]: #(CDT) 2018/10/30 12:25:49 - Running
130 OBMC_Sample/cp_post_stack
Michael Walshffee58a2016-11-22 11:28:33 -0600131 """
132
133 rc = 0
134
Michael Walshfa74bbb2018-10-30 13:21:03 -0500135 plug_in_packages_list = gp.get_var_value(plug_in_packages_list, [])
Michael Walshffee58a2016-11-22 11:28:33 -0600136
137 # If there are no plug-in packages to process, return successfully.
138 if len(plug_in_packages_list) == 0:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500139 if return_history:
140 return 0, 0, "", []
141 else:
142 return 0, 0, ""
Michael Walshffee58a2016-11-22 11:28:33 -0600143
Michael Walshfa74bbb2018-10-30 13:21:03 -0500144 quiet = int(gp.get_var_value(quiet, 0))
145 debug = int(gp.get_var_value(debug, 0))
Michael Walshffee58a2016-11-22 11:28:33 -0600146
147 # Create string from list.
148 plug_in_dir_paths = ':'.join(plug_in_packages_list)
149
150 temp = tempfile.NamedTemporaryFile()
151 temp_file_path = temp.name
152 temp2 = tempfile.NamedTemporaryFile()
153 temp_properties_file_path = temp2.name
154
Michael Walshfa74bbb2018-10-30 13:21:03 -0500155 if debug:
Michael Walshffee58a2016-11-22 11:28:33 -0600156 os.environ["PERF_TRACE"] = "1"
157 debug_string = " --quiet=0"
158 else:
159 debug_string = ""
160
161 loc_shell_rc = 0
162
163 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500164 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600165 str(shell_rc) + " --stop_on_plug_in_failure=" +\
166 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
167 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
Michael Walshfa74bbb2018-10-30 13:21:03 -0500168 if quiet:
Michael Walshffee58a2016-11-22 11:28:33 -0600169 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
170 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600171 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
172 temp_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500173 if debug:
174 gp.print_issuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600175 else:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500176 gp.print_timen("Processing " + call_point
177 + " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600178
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500179 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True,
180 executable='/bin/bash')
Michael Walshffee58a2016-11-22 11:28:33 -0600181
Michael Walshfa74bbb2018-10-30 13:21:03 -0500182 if return_history:
183 # Get the "Running" statements from the output.
184 regex = " Running [^/]+/cp_"
185 cmd_buf = "egrep '" + regex + "' " + temp_file_path
186 _, history = gc.shell_cmd(cmd_buf, quiet=(not debug), print_output=0,
187 show_err=0, ignore_err=1)
188 history = [x + "\n" for x in filter(None, history.split("\n"))]
189 else:
190 history = []
191
Michael Walshffee58a2016-11-22 11:28:33 -0600192 # As process_plug_in_packages.py help text states, it will print the
193 # values of failed_plug_in_name and shell_rc in the following format:
194 # failed_plug_in_name: <failed plug-in value, if any>
195 # shell_rc: <shell return code value of last
196 # call point program>
197
198 # We want to obtain those values from the output. To make the task
199 # simpler, we'll start by grepping the output for lines that might fit
200 # such a format:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500201 # A valid bash variable against the left margin followed by...
202 # - A colon followed by...
Michael Walshffee58a2016-11-22 11:28:33 -0600203 # - Zero or more spaces
Michael Walsh957a2b22017-05-30 17:56:13 -0500204 bash_var_regex = "[_[:alpha:]][_[:alnum:]]*"
205 regex = "^" + bash_var_regex + ":[ ]*"
206 cmd_buf = "egrep '" + regex + "' " + temp_file_path + " > " +\
207 temp_properties_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500208 gp.dprint_issuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500209 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600210
211 # Next we call my_parm_file to create a properties dictionary.
212 properties = gm.my_parm_file(temp_properties_file_path)
213
214 # Finally, we access the 2 values that we need.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500215 shell_rc = int(properties.get('shell_rc', '0x0000000000000000'), 16)
216 failed_plug_in_name = properties.get('failed_plug_in_name', '')
Michael Walshffee58a2016-11-22 11:28:33 -0600217
Michael Walsh957a2b22017-05-30 17:56:13 -0500218 if proc_plug_pkg_rc != 0:
Michael Walsh40822372017-01-10 11:33:08 -0600219 hex = 1
Michael Walshfa74bbb2018-10-30 13:21:03 -0500220 if grep_rc != 0:
221 gp.print_varx("grep_rc", grep_rc, hex)
222 gp.print_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
223 gp.print_timen("Re-cap of plug-in failures:")
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500224 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' "
Michael Walshfa74bbb2018-10-30 13:21:03 -0500225 + temp_properties_file_path + " | egrep -v '^\\--'",
226 quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600227 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600228
Michael Walshfa74bbb2018-10-30 13:21:03 -0500229 if return_history:
230 return rc, shell_rc, failed_plug_in_name, history
231 else:
232 return rc, shell_rc, failed_plug_in_name