blob: 5617f8be335578c08bcbfe5cdecb044139e7885d [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
18
19
20###############################################################################
21def 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
52###############################################################################
53
54
55###############################################################################
56def rprocess_plug_in_packages(plug_in_packages_list=None,
57 call_point="setup",
58 shell_rc="0x00000000",
59 stop_on_plug_in_failure=1,
60 stop_on_non_zero_rc=0,
61 release_type="obmc",
62 quiet=None,
63 debug=None):
64
65 r"""
66 Call the external process_plug_in_packages.py to process the plug-in
67 packages. Return the following:
68 rc The return code - 0 = PASS, 1 = FAIL.
69 shell_rc The shell return code returned by
70 process_plug_in_packages.py.
71 failed_plug_in_name The failed plug in name (if any).
72
73 Description of arguments:
74 plug_in_packages_list A python list of plug-in directory paths.
75 call_point The call point program to be called for
76 each plug-in package (e.g. post_boot).
77 This name should not include the "cp_"
78 prefix.
79 shell_rc The user may supply a value other than
80 zero to indicate an acceptable non-zero
81 return code. For example, if this value
82 equals 0x00000200, it means that for each
83 plug-in call point that runs, a 0x00000200
84 will not be counted as a failure.
85 stop_on_plug_in_failure If this parameter is set to 1, this
86 program will stop and return non-zero if
87 the call point program from any plug-in
88 directory fails. Conversely, if it is set
89 to false, this program will run the call
90 point program from each and every plug-in
91 directory regardless of their return
92 values. Typical example cases where you'd
93 want to run all plug-in call points
94 regardless of success or failure would be
95 "cleanup" or "ffdc" call points.
96 stop_on_non_zero_rc If this parm is set to 1 and a plug-in
97 call point program returns a valid
98 non-zero return code (see "shell_rc" parm
99 above), this program will stop processing
100 and return 0 (success). Since this
101 constitutes a successful exit, this would
102 normally be used where the caller wishes
103 to stop processing if one of the plug-in
104 directory call point programs returns a
105 special value indicating that some special
106 case has been found. An example might be
107 in calling some kind of "check_errl" call
108 point program. Such a call point program
109 might return a 2 (i.e. 0x00000200) to
110 indicate that a given error log entry was
111 found in an "ignore" list and is therefore
112 to be ignored. That being the case, no
113 other "check_errl" call point program
114 would need to be called.
115 release_type The type of release being tested (e.g.
116 "obmc", "op", "fips"). This influences
117 which integrated plug-ins are selected.
118 quiet If quiet is set to 1, this function will
119 NOT write status messages to stdout. This
120 will default to the global quiet program
121 parm or to 0.
122 debug If this parameter is set to 1, this
123 function will print additional debug
124 information. This is mainly to be used by
125 the developer of this function. This will
126 default to the global quiet program parm
127 or to 0.
128 """
129
130 rc = 0
131
132 if plug_in_packages_list is None:
133 plug_in_packages_list = BuiltIn().get_variable_value(
Michael Walsh40822372017-01-10 11:33:08 -0600134 "${plug_in_packages_list}")
Michael Walshffee58a2016-11-22 11:28:33 -0600135
136 # If there are no plug-in packages to process, return successfully.
137 if len(plug_in_packages_list) == 0:
138 return 0, 0, ""
139
140 if quiet is None:
141 try:
142 quiet = int(BuiltIn().get_variable_value("${quiet}"))
143 except TypeError:
144 quiet = 0
145
146 if debug is None:
147 try:
148 debug = int(BuiltIn().get_variable_value("${debug}"))
149 except TypeError:
150 debug = 0
151
152 # Create string from list.
153 plug_in_dir_paths = ':'.join(plug_in_packages_list)
154
155 temp = tempfile.NamedTemporaryFile()
156 temp_file_path = temp.name
157 temp2 = tempfile.NamedTemporaryFile()
158 temp_properties_file_path = temp2.name
159
160 if int(debug) == 1:
161 os.environ["PERF_TRACE"] = "1"
162 debug_string = " --quiet=0"
163 else:
164 debug_string = ""
165
166 loc_shell_rc = 0
167
168 sub_cmd_buf = "process_plug_in_packages.py" + debug_string +\
169 " --call_point=" + call_point + " --shell_rc=" +\
170 str(shell_rc) + " --stop_on_plug_in_failure=" +\
171 str(stop_on_plug_in_failure) + " --stop_on_non_zero_rc=" +\
172 str(stop_on_non_zero_rc) + " " + plug_in_dir_paths
173 if int(quiet) == 1:
174 cmd_buf = sub_cmd_buf + " > " + temp_file_path + " 2>&1"
175 else:
Michael Walsh4bb56c52016-12-09 13:57:15 -0600176 cmd_buf = "set -o pipefail ; " + sub_cmd_buf + " 2>&1 | tee " +\
177 temp_file_path
178
Michael Walshffee58a2016-11-22 11:28:33 -0600179 if int(debug) == 1:
180 grp.rpissuing(cmd_buf)
Michael Walsh40822372017-01-10 11:33:08 -0600181 grp.rprint_timen("Processing " + call_point + " call point programs.")
Michael Walshffee58a2016-11-22 11:28:33 -0600182
Michael Walsh40822372017-01-10 11:33:08 -0600183 proc_plug_pkg_rc = subprocess.call(cmd_buf, shell=True)
Michael Walshffee58a2016-11-22 11:28:33 -0600184
185 # As process_plug_in_packages.py help text states, it will print the
186 # values of failed_plug_in_name and shell_rc in the following format:
187 # failed_plug_in_name: <failed plug-in value, if any>
188 # shell_rc: <shell return code value of last
189 # call point program>
190
191 # We want to obtain those values from the output. To make the task
192 # simpler, we'll start by grepping the output for lines that might fit
193 # such a format:
194 # - Zero or more spaces
195 # - One or more non-colon characters
196 # - A colon
197 # - Zero or more spaces
Michael Walsh40822372017-01-10 11:33:08 -0600198 # I added code to exclude any line that starts with spaces and a
199 # left-square bracket (e.g. '[ ERROR ]'). These would be interpreted by
200 # my_parm_file as a new section.
201 cmd_buf = "egrep '^[ ]*[^:]+:[ ]*' " + temp_file_path +\
202 " | egrep -v '^[ ]*\[' > " + temp_properties_file_path
Michael Walshffee58a2016-11-22 11:28:33 -0600203 if int(debug) == 1:
204 grp.rpissuing(cmd_buf)
Michael Walsh40822372017-01-10 11:33:08 -0600205 gen_rc = os.system(cmd_buf)
Michael Walshffee58a2016-11-22 11:28:33 -0600206
207 # Next we call my_parm_file to create a properties dictionary.
208 properties = gm.my_parm_file(temp_properties_file_path)
209
210 # Finally, we access the 2 values that we need.
211 try:
Michael Walsh40822372017-01-10 11:33:08 -0600212 shell_rc = int(properties['shell_rc'], 16)
Michael Walshffee58a2016-11-22 11:28:33 -0600213 except KeyError:
214 shell_rc = 0
215 try:
216 failed_plug_in_name = properties['failed_plug_in_name']
217 except KeyError:
218 failed_plug_in_name = ""
219
Michael Walsh40822372017-01-10 11:33:08 -0600220 if gen_rc != 0 or proc_plug_pkg_rc != 0:
221 hex = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600222 grp.rprint_error("Call to process_plug_in_packages failed.\n")
Michael Walsh40822372017-01-10 11:33:08 -0600223 grp.rprint_varx("gen_rc", gen_rc, hex)
224 grp.rprint_varx("proc_plug_pkg_rc", proc_plug_pkg_rc, hex)
Michael Walshffee58a2016-11-22 11:28:33 -0600225 grp.rprint_varx("failed_plug_in_name", failed_plug_in_name)
Michael Walsh40822372017-01-10 11:33:08 -0600226 grp.rprint_varx("shell_rc", shell_rc, hex)
227 rc = 1
Michael Walshffee58a2016-11-22 11:28:33 -0600228
229 return rc, shell_rc, failed_plug_in_name
230
231###############################################################################