blob: e9fb54d32973ab2c0d3cd5f396a9fd6632effd99 [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
Michael Walshffee58a2016-11-22 11:28:33 -060021def rvalidate_plug_ins(plug_in_dir_paths,
22 quiet=1):
23
24 r"""
25 Call the external validate_plug_ins.py program which validates the plug-in
26 dir paths given to it. Return a list containing a normalized path for
27 each plug-in selected.
28
29 Description of arguments:
30 plug_in_dir_paths A colon-separated list of plug-in
31 directory paths.
32 quiet If quiet is set to 1, this function will
33 NOT write status messages to stdout.
34 """
35
36 cmd_buf = "validate_plug_ins.py \"" + plug_in_dir_paths + "\""
37 if int(quiet) != 1:
38 grp.rpissuing(cmd_buf)
39 rc, out_buf = commands.getstatusoutput(cmd_buf)
40 if rc != 0:
41 message = gp.sprint_varx("rc", rc, 1) + out_buf
42 grp.rprintn(out_buf, 'STDERR')
Michael Walsh4bb56c52016-12-09 13:57:15 -060043 BuiltIn().fail(gp.sprint_error("Validate plug ins call failed. See" +
44 " stderr text for details.\n"))
Michael Walshffee58a2016-11-22 11:28:33 -060045
46 plug_in_packages_list = out_buf.split("\n")
47 if len(plug_in_packages_list) == 1 and plug_in_packages_list[0] == "":
48 return []
49
50 return plug_in_packages_list
51
Michael Walshffee58a2016-11-22 11:28:33 -060052
Michael Walshffee58a2016-11-22 11:28:33 -060053def rprocess_plug_in_packages(plug_in_packages_list=None,
54 call_point="setup",
55 shell_rc="0x00000000",
56 stop_on_plug_in_failure=1,
57 stop_on_non_zero_rc=0,
58 release_type="obmc",
59 quiet=None,
60 debug=None):
61
62 r"""
63 Call the external process_plug_in_packages.py to process the plug-in
64 packages. Return the following:
65 rc The return code - 0 = PASS, 1 = FAIL.
66 shell_rc The shell return code returned by
67 process_plug_in_packages.py.
68 failed_plug_in_name The failed plug in name (if any).
69
70 Description of arguments:
71 plug_in_packages_list A python list of plug-in directory paths.
72 call_point The call point program to be called for
73 each plug-in package (e.g. post_boot).
74 This name should not include the "cp_"
75 prefix.
76 shell_rc The user may supply a value other than
77 zero to indicate an acceptable non-zero
78 return code. For example, if this value
79 equals 0x00000200, it means that for each
80 plug-in call point that runs, a 0x00000200
81 will not be counted as a failure.
82 stop_on_plug_in_failure If this parameter is set to 1, this
83 program will stop and return non-zero if
84 the call point program from any plug-in
85 directory fails. Conversely, if it is set
86 to false, this program will run the call
87 point program from each and every plug-in
88 directory regardless of their return
89 values. Typical example cases where you'd
90 want to run all plug-in call points
91 regardless of success or failure would be
92 "cleanup" or "ffdc" call points.
93 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
94 call point program returns a valid
95 non-zero return code (see "shell_rc" parm
96 above), this program will stop processing
97 and return 0 (success). Since this
98 constitutes a successful exit, this would
99 normally be used where the caller wishes
100 to stop processing if one of the plug-in
101 directory call point programs returns a
102 special value indicating that some special
103 case has been found. An example might be
104 in calling some kind of "check_errl" call
105 point program. Such a call point program
106 might return a 2 (i.e. 0x00000200) to
107 indicate that a given error log entry was
108 found in an "ignore" list and is therefore
109 to be ignored. That being the case, no
110 other "check_errl" call point program
111 would need to be called.
112 release_type The type of release being tested (e.g.
113 "obmc", "op", "fips"). This influences
114 which integrated plug-ins are selected.
115 quiet If quiet is set to 1, this function will
116 NOT write status messages to stdout. This
117 will default to the global quiet program
118 parm or to 0.
119 debug If this parameter is set to 1, this
120 function will print additional debug
121 information. This is mainly to be used by
122 the developer of this function. This will
123 default to the global quiet program parm
124 or to 0.
125 """
126
127 rc = 0
128
129 if plug_in_packages_list is None:
130 plug_in_packages_list = BuiltIn().get_variable_value(
Michael Walsh40822372017-01-10 11:33:08 -0600131 "${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:
135 return 0, 0, ""
136
137 if quiet is None:
138 try:
139 quiet = int(BuiltIn().get_variable_value("${quiet}"))
140 except TypeError:
141 quiet = 0
142
143 if debug is None:
144 try:
145 debug = int(BuiltIn().get_variable_value("${debug}"))
146 except TypeError:
147 debug = 0
148
149 # Create string from list.
150 plug_in_dir_paths = ':'.join(plug_in_packages_list)
151
152 temp = tempfile.NamedTemporaryFile()
153 temp_file_path = temp.name
154 temp2 = tempfile.NamedTemporaryFile()
155 temp_properties_file_path = temp2.name
156
157 if int(debug) == 1:
158 os.environ["PERF_TRACE"] = "1"
159 debug_string = " --quiet=0"
160 else:
161 debug_string = ""
162
163 loc_shell_rc = 0
164
165 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
Michael Walshed18ec72017-06-27 10:15:31 -0500166 " --call_point=" + call_point + " --allow_shell_rc=" +\
Michael Walshffee58a2016-11-22 11:28:33 -0600167 str(shell_rc) + " --stop_on_plug_in_failure=" +\
168 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
169 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
170 if int(quiet) == 1:
171 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
172 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600173 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
174 temp_file_path
175
Michael Walshffee58a2016-11-22 11:28:33 -0600176 if int(debug) == 1:
177 grp.rpissuing(cmd_buf)
Michael Walsh09305182017-02-20 16:10:03 -0600178 else:
179 grp.rprint_timen("Processing " + call_point +
180 " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600181
Michael Walsh40822372017-01-10 11:33:08 -0600182 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True)
Michael Walshffee58a2016-11-22 11:28:33 -0600183
184 # As process_plug_in_packages.py help text states, it will print the
185 # values of failed_plug_in_name and shell_rc in the following format:
186 # failed_plug_in_name: <failed plug-in value, if any>
187 # shell_rc: <shell return code value of last
188 # call point program>
189
190 # We want to obtain those values from the output. To make the task
191 # simpler, we'll start by grepping the output for lines that might fit
192 # such a format:
Michael Walsh957a2b22017-05-30 17:56:13 -0500193 # A valid bash variable against the left margin
Michael Walshffee58a2016-11-22 11:28:33 -0600194 # - A colon
195 # - Zero or more spaces
Michael Walsh957a2b22017-05-30 17:56:13 -0500196 bash_var_regex = "[_[:alpha:]][_[:alnum:]]*"
197 regex = "^" + bash_var_regex + ":[ ]*"
198 cmd_buf = "egrep '" + regex + "' " + temp_file_path + " > " +\
199 temp_properties_file_path
Michael Walshffee58a2016-11-22 11:28:33 -0600200 if int(debug) == 1:
201 grp.rpissuing(cmd_buf)
Michael Walsh957a2b22017-05-30 17:56:13 -0500202 grep_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600203
204 # Next we call my_parm_file to create a properties dictionary.
205 properties = gm.my_parm_file(temp_properties_file_path)
206
207 # Finally, we access the 2 values that we need.
208 try:
Michael Walsh40822372017-01-10 11:33:08 -0600209 shell_rc = int(properties['shell_rc'], 16)
Michael Walshffee58a2016-11-22 11:28:33 -0600210 except KeyError:
211 shell_rc = 0
212 try:
213 failed_plug_in_name = properties['failed_plug_in_name']
214 except KeyError:
215 failed_plug_in_name = ""
216
Michael Walsh957a2b22017-05-30 17:56:13 -0500217 if proc_plug_pkg_rc != 0:
Michael Walsh40822372017-01-10 11:33:08 -0600218 hex = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600219 grp.rprint_error("Call to process_plug_in_packages failed.\n")
Michael Walsh957a2b22017-05-30 17:56:13 -0500220 grp.rprint_varx("grep_rc", grep_rc, hex)
Michael Walsh40822372017-01-10 11:33:08 -0600221 grp.rprint_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
Michael Walsh957a2b22017-05-30 17:56:13 -0500222 # Show all of the failed plug in names and shell_rcs.
223 gc.cmd_fnc_u("egrep -A 1 '^failed_plug_in_name:[ ]+' " +
224 temp_properties_file_path, quiet=1, show_err=0)
Michael Walsh40822372017-01-10 11:33:08 -0600225 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600226
227 return rc, shell_rc, failed_plug_in_name