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