blob: 94a8b331dce275211f6e7672f05d719016e2e340 [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
16import gen_robot_print as grp
17import gen_misc as gm
Michael Walsh957a2b22017-05-30 17:56:13 -050018import gen_cmd as gc
Michael Walshffee58a2016-11-22 11:28:33 -060019
20
21###############################################################################
22def rvalidate_plug_ins(plug_in_dir_paths,
23 quiet=1):
24
25 r"""
26 Call the external validate_plug_ins.py program which validates the plug-in
27 dir paths given to it. Return a list containing a normalized path for
28 each plug-in selected.
29
30 Description of arguments:
31 plug_in_dir_paths A colon-separated list of plug-in
32 directory paths.
33 quiet If quiet is set to 1, this function will
34 NOT write status messages to stdout.
35 """
36
37 cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
38 if int(quiet) != 1:
39 grp.rpissuing(cmd_buf)
40 rc, out_buf = commands.getstatusoutput(cmd_buf)
41 if rc != 0:
42 message = gp.sprint_varx("rc", rc, 1) + out_buf
43 grp.rprintn(out_buf, 'STDERR')
Michael Walsh4bb56c52016-12-09 13:57:15 -060044 BuiltIn().fail(gp.sprint_error("Validate plug ins call failed. See" +
45 " stderr text for details.\n"))
Michael Walshffee58a2016-11-22 11:28:33 -060046
47 plug_in_packages_list = out_buf.split("\n")
48 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
49 return []
50
51 return plug_in_packages_list
52
53###############################################################################
54
55
56###############################################################################
57def rprocess_plug_in_packages(plug_in_packages_list=None,
58 call_point="setup",
59 shell_rc="0x00000000",
60 stop_on_plug_in_failure=1,
61 stop_on_non_zero_rc=0,
62 release_type="obmc",
63 quiet=None,
64 debug=None):
65
66 r"""
67 Call the external process_plug_in_packages.py to process the plug-in
68 packages. Return the following:
69 rc The return code - 0 = PASS, 1 = FAIL.
70 shell_rc The shell return code returned by
71 process_plug_in_packages.py.
72 failed_plug_in_name The failed plug in name (if any).
73
74 Description of arguments:
75 plug_in_packages_list A python list of plug-in directory paths.
76 call_point The call point program to be called for
77 each plug-in package (e.g. post_boot).
78 This name should not include the "cp_"
79 prefix.
80 shell_rc The user may supply a value other than
81 zero to indicate an acceptable non-zero
82 return code. For example, if this value
83 equals 0x00000200, it means that for each
84 plug-in call point that runs, a 0x00000200
85 will not be counted as a failure.
86 stop_on_plug_in_failure If this parameter is set to 1, this
87 program will stop and return non-zero if
88 the call point program from any plug-in
89 directory fails. Conversely, if it is set
90 to false, this program will run the call
91 point program from each and every plug-in
92 directory regardless of their return
93 values. Typical example cases where you'd
94 want to run all plug-in call points
95 regardless of success or failure would be
96 "cleanup" or "ffdc" call points.
97 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
98 call point program returns a valid
99 non-zero return code (see "shell_rc" parm
100 above), this program will stop processing
101 and return 0 (success). Since this
102 constitutes a successful exit, this would
103 normally be used where the caller wishes
104 to stop processing if one of the plug-in
105 directory call point programs returns a
106 special value indicating that some special
107 case has been found. An example might be
108 in calling some kind of "check_errl" call
109 point program. Such a call point program
110 might return a 2 (i.e. 0x00000200) to
111 indicate that a given error log entry was
112 found in an "ignore" list and is therefore
113 to be ignored. That being the case, no
114 other "check_errl" call point program
115 would need to be called.
116 release_type The type of release being tested (e.g.
117 "obmc", "op", "fips"). This influences
118 which integrated plug-ins are selected.
119 quiet If quiet is set to 1, this function will
120 NOT write status messages to stdout. This
121 will default to the global quiet program
122 parm or to 0.
123 debug If this parameter is set to 1, this
124 function will print additional debug
125 information. This is mainly to be used by
126 the developer of this function. This will
127 default to the global quiet program parm
128 or to 0.
129 """
130
131 rc = 0
132
133 if plug_in_packages_list is None:
134 plug_in_packages_list = BuiltIn().get_variable_value(
Michael Walsh40822372017-01-10 11:33:08 -0600135 "${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:
139 return 0, 0, ""
140
141 if quiet is None:
142 try:
143 quiet = int(BuiltIn().get_variable_value("${quiet}"))
144 except TypeError:
145 quiet = 0
146
147 if debug is None:
148 try:
149 debug = int(BuiltIn().get_variable_value("${debug}"))
150 except TypeError:
151 debug = 0
152
153 # Create string from list.
154 plug_in_dir_paths = ':'.join(plug_in_packages_list)
155
156 temp = tempfile.NamedTemporaryFile()
157 temp_file_path = temp.name
158 temp2 = tempfile.NamedTemporaryFile()
159 temp_properties_file_path = temp2.name
160
161 if int(debug) == 1:
162 os.environ["PERF_TRACE"] = "1"
163 debug_string = " --quiet=0"
164 else:
165 debug_string = ""
166
167 loc_shell_rc = 0
168
169 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500170 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600171 str(shell_rc) + " --stop_on_plug_in_failure=" +\
172 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
173 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
174 if int(quiet) == 1:
175 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
176 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600177 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
178 temp_file_path
179
Michael Walshffee58a2016-11-22 11:28:33 -0600180 if int(debug) == 1:
181 grp.rpissuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600182 else:
183 grp.rprint_timen("Processing " + call_point +
184 " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600185
Michael Walsh40822372017-01-10 11:33:08 -0600186 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True)
Michael Walshffee58a2016-11-22 11:28:33 -0600187
188 # 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 Walsh957a2b22017-05-30 17:56:13 -0500197 # A valid bash variable against the left margin
Michael Walshffee58a2016-11-22 11:28:33 -0600198 # - A colon
199 # - 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 Walshffee58a2016-11-22 11:28:33 -0600204 if int(debug) == 1:
205 grp.rpissuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500206 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600207
208 # Next we call my_parm_file to create a properties dictionary.
209 properties = gm.my_parm_file(temp_properties_file_path)
210
211 # Finally, we access the 2 values that we need.
212 try:
Michael Walsh40822372017-01-10 11:33:08 -0600213 shell_rc = int(properties['shell_rc'], 16)
Michael Walshffee58a2016-11-22 11:28:33 -0600214 except KeyError:
215 shell_rc = 0
216 try:
217 failed_plug_in_name = properties['failed_plug_in_name']
218 except KeyError:
219 failed_plug_in_name = ""
220
Michael Walsh957a2b22017-05-30 17:56:13 -0500221 if proc_plug_pkg_rc != 0:
Michael Walsh40822372017-01-10 11:33:08 -0600222 hex = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600223 grp.rprint_error("Call to process_plug_in_packages failed.\n")
Michael Walsh957a2b22017-05-30 17:56:13 -0500224 grp.rprint_varx("grep_rc", grep_rc, hex)
Michael Walsh40822372017-01-10 11:33:08 -0600225 grp.rprint_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
Michael Walsh957a2b22017-05-30 17:56:13 -0500226 # Show all of the failed plug in names and shell_rcs.
227 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' " +
228 temp_properties_file_path, quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600229 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600230
231 return rc, shell_rc, failed_plug_in_name
232
233###############################################################################