blob: 56fc19afee22fc9a3a68d513b164784fdd2febab [file] [log] [blame]
Michael Walsh3ba8ecd2018-04-24 11:33:25 -05001#!/usr/bin/env python
2
3r"""
4This module provides functions which are useful to plug-ins call-point
5programs that wish to make external robot program calls.
6"""
7
8import sys
9import os
10import subprocess
11import re
12import time
13import imp
14
15import gen_print as gp
16import gen_valid as gv
17import gen_misc as gm
18import gen_cmd as gc
19
Michael Walsh3ba8ecd2018-04-24 11:33:25 -050020base_path = \
21 os.path.dirname(os.path.dirname(imp.find_module("gen_robot_print")[1])) +\
22 os.sep
23
24
25def init_robot_out_parms(extra_prefix=""):
26
27 r"""
28 Initialize robot output parms such as outputdir, output, etc.
29
30 This function will set global values for the following robot output parms.
31
32 outputdir, output, log, report, loglevel
33
34 This function would typically be called prior to calling
35 create_robot_cmd_string.
36 """
37
38 AUTOBOOT_OPENBMC_NICKNAME = gm.get_mod_global("AUTOBOOT_OPENBMC_NICKNAME")
39
40 FFDC_DIR_PATH_STYLE = os.environ.get('FFDC_DIR_PATH_STYLE', '0')
41 if FFDC_DIR_PATH_STYLE == '1':
42 default_ffdc_dir_path = "/tmp/"
43 else:
44 default_ffdc_dir_path = base_path
45 # Set values for call to create_robot_cmd_string.
46 outputdir = gm.add_trailing_slash(os.environ.get("FFDC_DIR_PATH",
47 default_ffdc_dir_path))
48 seconds = time.time()
49 loc_time = time.localtime(seconds)
50 time_string = time.strftime("%y%m%d.%H%M%S", loc_time)
51 file_prefix = AUTOBOOT_OPENBMC_NICKNAME + "." + extra_prefix +\
52 time_string + "."
53 output = file_prefix + "output.xml"
54 log = file_prefix + "log.html"
55 report = file_prefix + "report.html"
56 loglevel = "TRACE"
57
58 # Make create_robot_cmd_string values global.
59 gm.set_mod_global(outputdir)
60 gm.set_mod_global(output)
61 gm.set_mod_global(log)
62 gm.set_mod_global(report)
63 gm.set_mod_global(loglevel)
64
65
66def init_robot_test_base_dir_path():
67
68 r"""
69 Initialize and validate the environment variable, ROBOT_TEST_BASE_DIR_PATH
70 and set corresponding global variable ROBOT_TEST_RUNNING_FROM_SB.
71
72 If ROBOT_TEST_BASE_DIR_PATH is already set, this function will merely
73 validate it. This function will also set environment variable
74 ROBOT_TEST_RUNNING_FROM_SB when ROBOT_TEST_BASE_DIR_PATH is not pre-set.
75 """
76
77 # ROBOT_TEST_BASE_DIR_PATH will be set as follows:
78 # This function will determine whether we are running in a user sandbox
79 # or from a standard apolloxxx environment.
80 # - User sandbox:
81 # If there is a <developer's home dir>/git/openbmc-test-automation/,
82 # ROBOT_TEST_BASE_DIR_PATH will be set to that path. Otherwise, we set it
83 # to <program dir path>/git/openbmc-test-automation/
84 # - Not in user sandbox:
85 # ROBOT_TEST_BASE_DIR_PATH will be set to <program dir
86 # path>/git/openbmc-test-automation/
87
88 ROBOT_TEST_BASE_DIR_PATH = os.environ.get('ROBOT_TEST_BASE_DIR_PATH', "")
Michael Walsh3ba8ecd2018-04-24 11:33:25 -050089 ROBOT_TEST_RUNNING_FROM_SB = \
90 int(os.environ.get('ROBOT_TEST_RUNNING_FROM_SB', "0"))
91 if ROBOT_TEST_BASE_DIR_PATH == "":
92 # ROBOT_TEST_BASE_DIR_PATH was not set by user/caller.
Michael Walsh3ba8ecd2018-04-24 11:33:25 -050093 AUTOIPL_VERSION = os.environ.get('AUTOIPL_VERSION', '')
Michael Walsh3ba8ecd2018-04-24 11:33:25 -050094 if AUTOIPL_VERSION == "":
95 ROBOT_TEST_BASE_DIR_PATH = base_path
96 else:
97 suffix = "git/openbmc-test-automation/"
98
99 # Determine whether we're running out of a developer sandbox or
100 # simply out of an apolloxxx/bin path.
Michael Walshbffaa1d2018-06-08 15:09:27 -0500101 shell_rc, out_buf = gc.shell_cmd('dirname $(which gen_print.py)',
102 quiet=(not debug), print_output=0)
103 executable_base_dir_path = os.path.realpath(out_buf.rstrip()) + "/"
104 apollo_dir_path = os.environ['AUTO_BASE_PATH'] + AUTOIPL_VERSION +\
105 "/bin/"
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500106 developer_home_dir_path = re.sub('/sandbox.*', '',
107 executable_base_dir_path)
108 developer_home_dir_path = \
109 gm.add_trailing_slash(developer_home_dir_path)
110 gp.dprint_vars(executable_base_dir_path, developer_home_dir_path,
111 apollo_dir_path)
112
113 ROBOT_TEST_RUNNING_FROM_SB = 0
114 if executable_base_dir_path != apollo_dir_path:
115 ROBOT_TEST_RUNNING_FROM_SB = 1
116 gp.dprint_vars(ROBOT_TEST_RUNNING_FROM_SB)
117 ROBOT_TEST_BASE_DIR_PATH = developer_home_dir_path + suffix
118 if not os.path.isdir(ROBOT_TEST_BASE_DIR_PATH):
119 gp.dprint_timen("NOTE: Sandbox directory" +
120 " ${ROBOT_TEST_BASE_DIR_PATH} does not" +
121 " exist.")
122 # Fall back to the apollo dir path.
123 ROBOT_TEST_BASE_DIR_PATH = apollo_dir_path + suffix
124 else:
125 # Use to the apollo dir path.
126 ROBOT_TEST_BASE_DIR_PATH = apollo_dir_path + suffix
127
128 if not gv.valid_value(ROBOT_TEST_BASE_DIR_PATH):
129 return False
130 gp.dprint_vars(ROBOT_TEST_RUNNING_FROM_SB, ROBOT_TEST_BASE_DIR_PATH)
131 if not gv.valid_dir_path(ROBOT_TEST_BASE_DIR_PATH):
132 return False
133
134 ROBOT_TEST_BASE_DIR_PATH = gm.add_trailing_slash(ROBOT_TEST_BASE_DIR_PATH)
135 gm.set_mod_global(ROBOT_TEST_BASE_DIR_PATH)
136 os.environ['ROBOT_TEST_BASE_DIR_PATH'] = ROBOT_TEST_BASE_DIR_PATH
137
138 gm.set_mod_global(ROBOT_TEST_RUNNING_FROM_SB)
139 os.environ['ROBOT_TEST_RUNNING_FROM_SB'] = str(ROBOT_TEST_RUNNING_FROM_SB)
140
141
142raw_robot_file_search_path = "${ROBOT_TEST_BASE_DIR_PATH}:" +\
143 "${ROBOT_TEST_BASE_DIR_PATH}tests:${ROBOT_TEST_BASE_DIR_PATH}extended:" +\
144 "${ROBOT_TEST_BASE_DIR_PATH}scratch:${PATH}"
145
146
147def init_robot_file_path(robot_file_path):
148
149 r"""
150 Determine full path name for the file path passed in robot_file_path and
151 return it.
152
153 If robot_file_path contains a fully qualified path name, this function
154 will verify that the file exists. If robot_file_path contains a relative
155 path, this function will search for the file and set robot_file_path so
156 that it contains the absolute path to the robot file. This function will
157 search for the robot file using the raw_robot_file_search_path (defined
158 above). Note that if ROBOT_TEST_BASE_DIR_PATH is not set, this function
159 will call init_robot_test_base_dir_path to set it.
160
161 Description of arguments:
162 robot_file_path The absolute or relative path to a robot
163 file.
164 """
165
166 if not gv.valid_value(robot_file_path):
167 raise ValueError('Programmer error.')
168
169 try:
170 if ROBOT_TEST_BASE_DIR_PATH is NONE:
171 init_robot_test_base_dir_path()
172 except NameError:
173 init_robot_test_base_dir_path()
174
175 if not re.match(r".*\.(robot|py)$", robot_file_path):
176 # No suffix so we'll assign one of "\.robot".
177 robot_file_path = robot_file_path + ".robot"
178
179 abs_path = 0
180 if robot_file_path[0:1] == "/":
181 abs_path = 1
182
183 gp.dprint_vars(abs_path, robot_file_path)
184
185 if not abs_path:
186 cmd_buf = "echo -n \"" + raw_robot_file_search_path + "\""
Michael Walshbffaa1d2018-06-08 15:09:27 -0500187 shell_rc, out_buf = gc.shell_cmd(cmd_buf, quiet=(not debug),
188 print_output=0)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500189 robot_file_search_paths = out_buf
190 gp.dpvar(robot_file_search_paths)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500191 robot_file_search_paths_list = robot_file_search_paths.split(':')
192 for search_path in robot_file_search_paths_list:
193 search_path = gm.add_trailing_slash(search_path)
194 candidate_file_path = search_path + robot_file_path
195 gp.dprint_var(candidate_file_path)
196 if os.path.isfile(candidate_file_path):
197 gp.dprint_timen("Found full path to " + robot_file_path + ".")
198 robot_file_path = candidate_file_path
199 break
200
201 gp.dprint_var(robot_file_path)
202 if not gv.valid_file_path(robot_file_path):
203 raise ValueError('Programmer error.')
204
205 return robot_file_path
206
207
208def get_robot_parm_names():
209
210 r"""
211 Return a list containing all of the long parm names (e.g. --outputdir)
212 supported by the robot program. Double dashes are not included in the
213 names returned.
214 """
215
216 cmd_buf = "robot -h | egrep " +\
217 "'^([ ]\-[a-zA-Z0-9])?[ ]+--[a-zA-Z0-9]+[ ]+' | sed -re" +\
218 " s'/.*\-\-//g' -e s'/ .*//g' | sort -u"
Michael Walshbffaa1d2018-06-08 15:09:27 -0500219 shell_rc, out_buf = gc.shell_cmd(cmd_buf, quiet=1, print_output=0)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500220
221 return out_buf.split("\n")
222
223
224def create_robot_cmd_string(robot_file_path, *parms):
225
226 r"""
227 Create a robot command string and return it. On failure, return an empty
228 string.
229
230 Description of arguments:
231 robot_file_path The path to the robot file to be run.
232 parms The list of parms to be included in the
233 command string. The name of each variable
234 in this list must be the same as the name
235 of the corresponding parm. This function
236 figures out that name. This function is
237 also able to distinguish robot parms (e.g.
238 --outputdir) from robot program parms (all
239 other parms which will be passed as "-v
240 PARM_NAME:parm_value")..
241
242 Example:
243
244 The following call to this function...
245 cmd_buf = create_robot_cmd_string("tools/start_sol_console.robot",
246 OPENBMC_HOST, quiet, test_mode, debug, outputdir, output, log, report)
247
248 Would return a string something like this.
249 robot -v OPENBMC_HOST:beye6 -v quiet:0 -v test_mode:1 -v debug:1
250 --outputdir=/gsa/ausgsa/projects/a/autoipl/status
251 --output=beye6.OS_Console.output.xml --log=beye6.OS_Console.log.html
252 --report=beye6.OS_Console.report.html tools/start_sol_console.robot
253 """
254
255 robot_file_path = init_robot_file_path(robot_file_path)
256
257 robot_parm_names = get_robot_parm_names()
258
259 robot_parm_list = []
260
261 stack_frame = 2
262 ix = 2
263 for arg in parms:
264 parm = arg
265 parm = gm.quote_bash_parm(gm.escape_bash_quotes(str(parm)))
266 var_name = gp.get_arg_name(None, ix, stack_frame)
267 if var_name in robot_parm_names:
268 p_string = "--" + var_name + "=" + str(parm)
269 robot_parm_list.append(p_string)
270 else:
271 p_string = "-v " + var_name + ":" + str(parm)
272 robot_parm_list.append(p_string)
273 ix += 1
274
275 robot_cmd_buf = "robot " + ' '.join(robot_parm_list) + " " +\
276 robot_file_path
277
278 return robot_cmd_buf
279
280
281def robot_cmd_fnc(robot_cmd_buf,
282 robot_jail=os.environ.get('ROBOT_JAIL', ''),
283 gzip=1):
284
285 r"""
286 Run the robot command string.
287
288 This function will set the various PATH variables correctly so that you
289 are running the proper version of all imported files, etc.
290
291 Description of argument(s):
292 robot_cmd_buf The complete robot command string.
293 robot_jail Indicates that this is to run in "robot
294 jail" meaning without visibility to any
295 apolloxxx import files, programs, etc.
296 gqip This indicates that the log, report and
297 output files produced by robot should be
298 gzipped to save space.
299 """
300
301 if not gv.valid_value(robot_cmd_buf):
302 return False
303
304 # Get globals set by init_robot_test_base_dir_path().
305 module = sys.modules["__main__"]
306 try:
307 ROBOT_TEST_BASE_DIR_PATH = getattr(module, "ROBOT_TEST_BASE_DIR_PATH")
308 except NameError:
309 init_robot_test_base_dir_path()
310 ROBOT_TEST_BASE_DIR_PATH = getattr(module, "ROBOT_TEST_BASE_DIR_PATH")
311
312 ROBOT_TEST_RUNNING_FROM_SB = \
313 gm.get_mod_global("ROBOT_TEST_RUNNING_FROM_SB")
314
315 if robot_jail == "":
316 if ROBOT_TEST_RUNNING_FROM_SB:
317 robot_jail = 0
318 else:
319 robot_jail = 1
320
321 robot_jail = int(robot_jail)
322 ROBOT_JAIL = os.environ.get('ROBOT_JAIL', '')
323 gp.dprint_vars(ROBOT_TEST_BASE_DIR_PATH, ROBOT_TEST_RUNNING_FROM_SB,
324 ROBOT_JAIL, robot_jail)
325
326 # Save PATH and PYTHONPATH to be restored later.
327 os.environ["SAVED_PYTHONPATH"] = os.environ.get("PYTHONPATH", "")
328 os.environ["SAVED_PATH"] = os.environ.get("PATH", "")
329
330 if robot_jail:
331 PYTHONPATH = ROBOT_TEST_BASE_DIR_PATH + "lib"
332 NEW_PATH_LIST = [ROBOT_TEST_BASE_DIR_PATH + "bin"]
333 # Coding special case to preserve python27_path.
334 python27_path = "/opt/rh/python27/root/usr/bin"
335 PATH_LIST = os.environ.get("PATH", "").split(":")
336 if python27_path in PATH_LIST:
337 NEW_PATH_LIST.append(python27_path)
338 NEW_PATH_LIST.extend(["/usr/local/sbin", "/usr/local/bin", "/usr/sbin",
339 "/usr/bin", "/sbin", "/bin"])
340 PATH = ":".join(NEW_PATH_LIST)
341 else:
342 PYTHONPATH = os.environ.get('PYTHONPATH', '') + ":" +\
343 ROBOT_TEST_BASE_DIR_PATH + "lib/"
344 PATH = os.environ.get('PATH', '') + ":" + ROBOT_TEST_BASE_DIR_PATH +\
345 "bin/"
346
347 os.environ['PYTHONPATH'] = PYTHONPATH
348 os.environ['PATH'] = PATH
349 gp.dprint_vars(PATH, PYTHONPATH)
350
351 os.environ['FFDC_DIR_PATH_STYLE'] = os.environ.get('FFDC_DIR_PATH_STYLE',
352 '1')
353
354 test_mode = getattr(module, "test_mode")
355
356 gp.qpissuing(robot_cmd_buf, test_mode)
357 if test_mode:
358 os.environ["PATH"] = os.environ.get("SAVED_PATH", "")
359 os.environ["PYTHONPATH"] = os.environ.get("SAVED_PYTHONPATH", "")
360 return True
361
362 if quiet:
363 DEVNULL = open(os.devnull, 'wb')
364 stdout = DEVNULL
365 else:
366 stdout = None
367 sub_proc = subprocess.Popen(robot_cmd_buf, stdout=stdout, shell=True)
368 sub_proc.communicate()
369 shell_rc = sub_proc.returncode
370 if shell_rc != 0:
371 hex = 1
372 gp.pvar(shell_rc, hex)
373 os.environ["PATH"] = os.environ.get("SAVED_PATH", "")
374 os.environ["PYTHONPATH"] = os.environ.get("SAVED_PYTHONPATH", "")
375 return False
376
377 os.environ["PATH"] = os.environ.get("SAVED_PATH", "")
378 os.environ["PYTHONPATH"] = os.environ.get("SAVED_PYTHONPATH", "")
379
380 if not gzip:
381 return True
382
383 # gzip the output files.
384 # Retrieve the parms from the robot command buffer.
385 robot_cmd_buf_dict = gc.parse_command_string(robot_cmd_buf)
386 # Get prefix from the log parm.
387 prefix = re.sub('log\.html$', '', robot_cmd_buf_dict['log'])
388 gp.qprintn()
389 rc, outbuf = gc.cmd_fnc("cd " + robot_cmd_buf_dict['outputdir'] +
390 " ; gzip " + robot_cmd_buf_dict['output'] +
391 " " + robot_cmd_buf_dict['log'] +
392 " " + robot_cmd_buf_dict['report'])
393
394 outputdir = gm.add_trailing_slash(robot_cmd_buf_dict['outputdir'])
395 Output = outputdir + robot_cmd_buf_dict['output'] + ".gz"
396 Log = outputdir + robot_cmd_buf_dict['log'] + ".gz"
397 Report = outputdir + robot_cmd_buf_dict['report'] + ".gz"
398 gp.qprintn("\ngzipped output:")
399 gp.qpvars(0, 9, Output, Log, Report)
400
401 return True