blob: a5ce32331de9c79c3222a946e7fda08274e05602 [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 + "\""
George Keishing569796c2019-06-10 13:25:53 -050039 rc, out_buf = gc.shell_cmd(cmd_buf, print_output=0)
Michael Walshffee58a2016-11-22 11:28:33 -060040 if rc != 0:
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
George Keishing569796c2019-06-10 13:25:53 -050044 # plug_in_packages_list = out_buf.split("\n")
45 plug_in_packages_list = list(filter(None, out_buf.split("\n")))
Michael Walshffee58a2016-11-22 11:28:33 -060046 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
47 return []
48
49 return plug_in_packages_list
50
Michael Walshffee58a2016-11-22 11:28:33 -060051
Michael Walshffee58a2016-11-22 11:28:33 -060052def rprocess_plug_in_packages(plug_in_packages_list=None,
53 call_point="setup",
54 shell_rc="0x00000000",
55 stop_on_plug_in_failure=1,
56 stop_on_non_zero_rc=0,
57 release_type="obmc",
58 quiet=None,
Michael Walshfa74bbb2018-10-30 13:21:03 -050059 debug=None,
60 return_history=False):
Michael Walshffee58a2016-11-22 11:28:33 -060061 r"""
62 Call the external process_plug_in_packages.py to process the plug-in
63 packages. Return the following:
64 rc The return code - 0 = PASS, 1 = FAIL.
65 shell_rc The shell return code returned by
66 process_plug_in_packages.py.
67 failed_plug_in_name The failed plug in name (if any).
68
69 Description of arguments:
70 plug_in_packages_list A python list of plug-in directory paths.
71 call_point The call point program to be called for
72 each plug-in package (e.g. post_boot).
73 This name should not include the "cp_"
74 prefix.
75 shell_rc The user may supply a value other than
76 zero to indicate an acceptable non-zero
77 return code. For example, if this value
78 equals 0x00000200, it means that for each
79 plug-in call point that runs, a 0x00000200
80 will not be counted as a failure.
81 stop_on_plug_in_failure If this parameter is set to 1, this
82 program will stop and return non-zero if
83 the call point program from any plug-in
84 directory fails. Conversely, if it is set
85 to false, this program will run the call
86 point program from each and every plug-in
87 directory regardless of their return
88 values. Typical example cases where you'd
89 want to run all plug-in call points
90 regardless of success or failure would be
91 "cleanup" or "ffdc" call points.
92 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
93 call point program returns a valid
94 non-zero return code (see "shell_rc" parm
95 above), this program will stop processing
96 and return 0 (success). Since this
97 constitutes a successful exit, this would
98 normally be used where the caller wishes
99 to stop processing if one of the plug-in
100 directory call point programs returns a
101 special value indicating that some special
102 case has been found. An example might be
103 in calling some kind of "check_errl" call
104 point program. Such a call point program
105 might return a 2 (i.e. 0x00000200) to
106 indicate that a given error log entry was
107 found in an "ignore" list and is therefore
108 to be ignored. That being the case, no
109 other "check_errl" call point program
110 would need to be called.
111 release_type The type of release being tested (e.g.
112 "obmc", "op", "fips"). This influences
113 which integrated plug-ins are selected.
114 quiet If quiet is set to 1, this function will
115 NOT write status messages to stdout. This
116 will default to the global quiet program
117 parm or to 0.
118 debug If this parameter is set to 1, this
119 function will print additional debug
120 information. This is mainly to be used by
121 the developer of this function. This will
122 default to the global quiet program parm
123 or to 0.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500124 return_history In addition to rc, shell_rc and
125 failed_plug_in_name, return a list
126 containing historical output that looks
127 like the following:
128
129 history:
130 history[0]: #(CDT) 2018/10/30 12:25:49 - Running
131 OBMC_Sample/cp_post_stack
Michael Walshffee58a2016-11-22 11:28:33 -0600132 """
133
134 rc = 0
135
Michael Walshfa74bbb2018-10-30 13:21:03 -0500136 plug_in_packages_list = gp.get_var_value(plug_in_packages_list, [])
Michael Walshffee58a2016-11-22 11:28:33 -0600137
138 # If there are no plug-in packages to process, return successfully.
139 if len(plug_in_packages_list) == 0:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500140 if return_history:
141 return 0, 0, "", []
142 else:
143 return 0, 0, ""
Michael Walshffee58a2016-11-22 11:28:33 -0600144
Michael Walshfa74bbb2018-10-30 13:21:03 -0500145 quiet = int(gp.get_var_value(quiet, 0))
146 debug = int(gp.get_var_value(debug, 0))
Michael Walshffee58a2016-11-22 11:28:33 -0600147
148 # Create string from list.
149 plug_in_dir_paths = ':'.join(plug_in_packages_list)
150
151 temp = tempfile.NamedTemporaryFile()
152 temp_file_path = temp.name
153 temp2 = tempfile.NamedTemporaryFile()
154 temp_properties_file_path = temp2.name
155
Michael Walshfa74bbb2018-10-30 13:21:03 -0500156 if debug:
Michael Walshffee58a2016-11-22 11:28:33 -0600157 os.environ["PERF_TRACE"] = "1"
158 debug_string = " --quiet=0"
159 else:
160 debug_string = ""
161
162 loc_shell_rc = 0
163
164 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500165 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600166 str(shell_rc) + " --stop_on_plug_in_failure=" +\
167 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
168 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
Michael Walshfa74bbb2018-10-30 13:21:03 -0500169 if quiet:
Michael Walshffee58a2016-11-22 11:28:33 -0600170 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
171 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600172 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
173 temp_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500174 if debug:
175 gp.print_issuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600176 else:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500177 gp.print_timen("Processing " + call_point
178 + " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600179
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500180 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True,
181 executable='/bin/bash')
Michael Walshffee58a2016-11-22 11:28:33 -0600182
Michael Walshfa74bbb2018-10-30 13:21:03 -0500183 if return_history:
184 # Get the "Running" statements from the output.
185 regex = " Running [^/]+/cp_"
186 cmd_buf = "egrep '" + regex + "' " + temp_file_path
187 _, history = gc.shell_cmd(cmd_buf, quiet=(not debug), print_output=0,
188 show_err=0, ignore_err=1)
189 history = [x + "\n" for x in filter(None, history.split("\n"))]
190 else:
191 history = []
192
Michael Walshffee58a2016-11-22 11:28:33 -0600193 # As process_plug_in_packages.py help text states, it will print the
194 # values of failed_plug_in_name and shell_rc in the following format:
195 # failed_plug_in_name: <failed plug-in value, if any>
196 # shell_rc: <shell return code value of last
197 # call point program>
198
199 # We want to obtain those values from the output. To make the task
200 # simpler, we'll start by grepping the output for lines that might fit
201 # such a format:
Michael Walshfa74bbb2018-10-30 13:21:03 -0500202 # A valid bash variable against the left margin followed by...
203 # - A colon followed by...
Michael Walshffee58a2016-11-22 11:28:33 -0600204 # - Zero or more spaces
Michael Walsh957a2b22017-05-30 17:56:13 -0500205 bash_var_regex = "[_[:alpha:]][_[:alnum:]]*"
206 regex = "^" + bash_var_regex + ":[ ]*"
207 cmd_buf = "egrep '" + regex + "' " + temp_file_path + " > " +\
208 temp_properties_file_path
Michael Walshfa74bbb2018-10-30 13:21:03 -0500209 gp.dprint_issuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500210 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600211
212 # Next we call my_parm_file to create a properties dictionary.
213 properties = gm.my_parm_file(temp_properties_file_path)
214
215 # Finally, we access the 2 values that we need.
Michael Walshfa74bbb2018-10-30 13:21:03 -0500216 shell_rc = int(properties.get('shell_rc', '0x0000000000000000'), 16)
217 failed_plug_in_name = properties.get('failed_plug_in_name', '')
Michael Walshffee58a2016-11-22 11:28:33 -0600218
Michael Walsh957a2b22017-05-30 17:56:13 -0500219 if proc_plug_pkg_rc != 0:
Michael Walsh40822372017-01-10 11:33:08 -0600220 hex = 1
Michael Walshfa74bbb2018-10-30 13:21:03 -0500221 if grep_rc != 0:
222 gp.print_varx("grep_rc", grep_rc, hex)
223 gp.print_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
224 gp.print_timen("Re-cap of plug-in failures:")
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500225 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' "
Michael Walshfa74bbb2018-10-30 13:21:03 -0500226 + temp_properties_file_path + " | egrep -v '^\\--'",
227 quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600228 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600229
Michael Walshfa74bbb2018-10-30 13:21:03 -0500230 if return_history:
231 return rc, shell_rc, failed_plug_in_name, history
232 else:
233 return rc, shell_rc, failed_plug_in_name