blob: cfcb66043617fc5704950e3b564a8b8412eb0067 [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
George Keishingc191ed72019-06-10 07:45:59 -050011try:
12 import commands
13except ImportError:
14 import subprocess
15
Michael Walshffee58a2016-11-22 11:28:33 -060016import os
17import tempfile
18
19import gen_print as gp
Michael Walshffee58a2016-11-22 11:28:33 -060020import gen_misc as gm
Michael Walsh957a2b22017-05-30 17:56:13 -050021import gen_cmd as gc
Michael Walshffee58a2016-11-22 11:28:33 -060022
23
Michael Walshffee58a2016-11-22 11:28:33 -060024def rvalidate_plug_ins(plug_in_dir_paths,
25 quiet=1):
Michael Walshffee58a2016-11-22 11:28:33 -060026 r"""
27 Call the external validate_plug_ins.py program which validates the plug-in
28 dir paths given to it. Return a list containing a normalized path for
29 each plug-in selected.
30
31 Description of arguments:
32 plug_in_dir_paths A colon-separated list of plug-in
33 directory paths.
34 quiet If quiet is set to 1, this function will
35 NOT write status messages to stdout.
36 """
37
38 cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
39 if int(quiet) != 1:
Michael Walshfa74bbb2018-10-30 13:21:03 -050040 gp.print_issuing(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -060041 rc, out_buf = commands.getstatusoutput(cmd_buf)
42 if rc != 0:
43 message = gp.sprint_varx("rc", rc, 1) + out_buf
Michael Walshfa74bbb2018-10-30 13:21:03 -050044 gp.printn(out_buf, 'STDERR')
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -050045 BuiltIn().fail(gp.sprint_error("Validate plug ins call failed. See"
46 + " stderr text for details.\n"))
Michael Walshffee58a2016-11-22 11:28:33 -060047
48 plug_in_packages_list = out_buf.split("\n")
49 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
50 return []
51
52 return plug_in_packages_list
53
Michael Walshffee58a2016-11-22 11:28:33 -060054
Michael Walshffee58a2016-11-22 11:28:33 -060055def rprocess_plug_in_packages(plug_in_packages_list=None,
56 call_point="setup",
57 shell_rc="0x00000000",
58 stop_on_plug_in_failure=1,
59 stop_on_non_zero_rc=0,
60 release_type="obmc",
61 quiet=None,
Michael Walshfa74bbb2018-10-30 13:21:03 -050062 debug=None,
63 return_history=False):
Michael Walshffee58a2016-11-22 11:28:33 -060064 r"""
65 Call the external process_plug_in_packages.py to process the plug-in
66 packages. Return the following:
67 rc The return code - 0 = PASS, 1 = FAIL.
68 shell_rc The shell return code returned by
69 process_plug_in_packages.py.
70 failed_plug_in_name The failed plug in name (if any).
71
72 Description of arguments:
73 plug_in_packages_list A python list of plug-in directory paths.
74 call_point The call point program to be called for
75 each plug-in package (e.g. post_boot).
76 This name should not include the "cp_"
77 prefix.
78 shell_rc The user may supply a value other than
79 zero to indicate an acceptable non-zero
80 return code. For example, if this value
81 equals 0x00000200, it means that for each
82 plug-in call point that runs, a 0x00000200
83 will not be counted as a failure.
84 stop_on_plug_in_failure If this parameter is set to 1, this
85 program will stop and return non-zero if
86 the call point program from any plug-in
87 directory fails. Conversely, if it is set
88 to false, this program will run the call
89 point program from each and every plug-in
90 directory regardless of their return
91 values. Typical example cases where you'd
92 want to run all plug-in call points
93 regardless of success or failure would be
94 "cleanup" or "ffdc" call points.
95 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
96 call point program returns a valid
97 non-zero return code (see "shell_rc" parm
98 above), this program will stop processing
99 and return 0 (success). Since this
100 constitutes a successful exit, this would
101 normally be used where the caller wishes
102 to stop processing if one of the plug-in
103 directory call point programs returns a
104 special value indicating that some special
105 case has been found. An example might be
106 in calling some kind of "check_errl" call
107 point program. Such a call point program
108 might return a 2 (i.e. 0x00000200) to
109 indicate that a given error log entry was
110 found in an "ignore" list and is therefore
111 to be ignored. That being the case, no
112 other "check_errl" call point program
113 would need to be called.
114 release_type The type of release being tested (e.g.
115 "obmc", "op", "fips"). This influences
116 which integrated plug-ins are selected.
117 quiet If quiet is set to 1, this function will
118 NOT write status messages to stdout. This
119 will default to the global quiet program
120 parm or to 0.
121 debug If this parameter is set to 1, this
122 function will print additional debug
123 information. This is mainly to be used by
124 the developer of this function. This will
125 default to the global quiet program parm
126 or to 0.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500127 return_history In addition to rc, shell_rc and
128 failed_plug_in_name, return a list
129 containing historical output that looks
130 like the following:
131
132 history:
133 history[0]: #(CDT) 2018/10/30 12:25:49 - Running
134 OBMC_Sample/cp_post_stack
Michael Walshffee58a2016-11-22 11:28:33 -0600135 """
136
137 rc = 0
138
Michael Walshfa74bbb2018-10-30 13:21:03 -0500139 plug_in_packages_list = gp.get_var_value(plug_in_packages_list, [])
Michael Walshffee58a2016-11-22 11:28:33 -0600140
141 # If there are no plug-in packages to process, return successfully.
142 if len(plug_in_packages_list) == 0:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500143 if return_history:
144 return 0, 0, "", []
145 else:
146 return 0, 0, ""
Michael Walshffee58a2016-11-22 11:28:33 -0600147
Michael Walshfa74bbb2018-10-30 13:21:03 -0500148 quiet = int(gp.get_var_value(quiet, 0))
149 debug = int(gp.get_var_value(debug, 0))
Michael Walshffee58a2016-11-22 11:28:33 -0600150
151 # Create string from list.
152 plug_in_dir_paths = ':'.join(plug_in_packages_list)
153
154 temp = tempfile.NamedTemporaryFile()
155 temp_file_path = temp.name
156 temp2 = tempfile.NamedTemporaryFile()
157 temp_properties_file_path = temp2.name
158
Michael Walshfa74bbb2018-10-30 13:21:03 -0500159 if debug:
Michael Walshffee58a2016-11-22 11:28:33 -0600160 os.environ["PERF_TRACE"] = "1"
161 debug_string = " --quiet=0"
162 else:
163 debug_string = ""
164
165 loc_shell_rc = 0
166
167 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500168 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600169 str(shell_rc) + " --stop_on_plug_in_failure=" +\
170 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
171 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
Michael Walshfa74bbb2018-10-30 13:21:03 -0500172 if quiet:
Michael Walshffee58a2016-11-22 11:28:33 -0600173 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
174 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600175 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
176 temp_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500177 if debug:
178 gp.print_issuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600179 else:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500180 gp.print_timen("Processing " + call_point
181 + " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600182
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500183 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True,
184 executable='/bin/bash')
Michael Walshffee58a2016-11-22 11:28:33 -0600185
Michael Walshfa74bbb2018-10-30 13:21:03 -0500186 if return_history:
187 # Get the "Running" statements from the output.
188 regex = " Running [^/]+/cp_"
189 cmd_buf = "egrep '" + regex + "' " + temp_file_path
190 _, history = gc.shell_cmd(cmd_buf, quiet=(not debug), print_output=0,
191 show_err=0, ignore_err=1)
192 history = [x + "\n" for x in filter(None, history.split("\n"))]
193 else:
194 history = []
195
Michael Walshffee58a2016-11-22 11:28:33 -0600196 # As process_plug_in_packages.py help text states, it will print the
197 # values of failed_plug_in_name and shell_rc in the following format:
198 # failed_plug_in_name: <failed plug-in value, if any>
199 # shell_rc: <shell return code value of last
200 # call point program>
201
202 # We want to obtain those values from the output. To make the task
203 # simpler, we'll start by grepping the output for lines that might fit
204 # such a format:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500205 # A valid bash variable against the left margin followed by...
206 # - A colon followed by...
Michael Walshffee58a2016-11-22 11:28:33 -0600207 # - Zero or more spaces
Michael Walsh957a2b22017-05-30 17:56:13 -0500208 bash_var_regex = "[_[:alpha:]][_[:alnum:]]*"
209 regex = "^" + bash_var_regex + ":[ ]*"
210 cmd_buf = "egrep '" + regex + "' " + temp_file_path + " > " +\
211 temp_properties_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500212 gp.dprint_issuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500213 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600214
215 # Next we call my_parm_file to create a properties dictionary.
216 properties = gm.my_parm_file(temp_properties_file_path)
217
218 # Finally, we access the 2 values that we need.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500219 shell_rc = int(properties.get('shell_rc', '0x0000000000000000'), 16)
220 failed_plug_in_name = properties.get('failed_plug_in_name', '')
Michael Walshffee58a2016-11-22 11:28:33 -0600221
Michael Walsh957a2b22017-05-30 17:56:13 -0500222 if proc_plug_pkg_rc != 0:
Michael Walsh40822372017-01-10 11:33:08 -0600223 hex = 1
Michael Walshfa74bbb2018-10-30 13:21:03 -0500224 if grep_rc != 0:
225 gp.print_varx("grep_rc", grep_rc, hex)
226 gp.print_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
227 gp.print_timen("Re-cap of plug-in failures:")
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500228 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' "
Michael Walshfa74bbb2018-10-30 13:21:03 -0500229 + temp_properties_file_path + " | egrep -v '^\\--'",
230 quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600231 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600232
Michael Walshfa74bbb2018-10-30 13:21:03 -0500233 if return_history:
234 return rc, shell_rc, failed_plug_in_name, history
235 else:
236 return rc, shell_rc, failed_plug_in_name