| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 1 | #!/usr/bin/env python | 
 | 2 |  | 
 | 3 | r""" | 
 | 4 | This module provides functions which are useful to plug-ins call-point | 
 | 5 | programs that wish to make external robot program calls. | 
 | 6 | """ | 
 | 7 |  | 
 | 8 | import sys | 
 | 9 | import os | 
 | 10 | import subprocess | 
 | 11 | import re | 
 | 12 | import time | 
 | 13 | import imp | 
 | 14 |  | 
 | 15 | import gen_print as gp | 
 | 16 | import gen_valid as gv | 
 | 17 | import gen_misc as gm | 
 | 18 | import gen_cmd as gc | 
 | 19 |  | 
| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 20 | base_path = \ | 
 | 21 |     os.path.dirname(os.path.dirname(imp.find_module("gen_robot_print")[1])) +\ | 
 | 22 |     os.sep | 
 | 23 |  | 
 | 24 |  | 
 | 25 | def 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 |  | 
 | 66 | def 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 Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 89 |     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 Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 93 |         AUTOIPL_VERSION = os.environ.get('AUTOIPL_VERSION', '') | 
| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 94 |         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 Walsh | bffaa1d | 2018-06-08 15:09:27 -0500 | [diff] [blame] | 101 |             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 Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 106 |             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 |  | 
 | 142 | raw_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 |  | 
 | 147 | def 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 Walsh | bffaa1d | 2018-06-08 15:09:27 -0500 | [diff] [blame] | 187 |         shell_rc, out_buf = gc.shell_cmd(cmd_buf, quiet=(not debug), | 
 | 188 |                                          print_output=0) | 
| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 189 |         robot_file_search_paths = out_buf | 
 | 190 |         gp.dpvar(robot_file_search_paths) | 
| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 191 |         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 |  | 
 | 208 | def 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 Walsh | bffaa1d | 2018-06-08 15:09:27 -0500 | [diff] [blame] | 219 |     shell_rc, out_buf = gc.shell_cmd(cmd_buf, quiet=1, print_output=0) | 
| Michael Walsh | 3ba8ecd | 2018-04-24 11:33:25 -0500 | [diff] [blame] | 220 |  | 
 | 221 |     return out_buf.split("\n") | 
 | 222 |  | 
 | 223 |  | 
 | 224 | def 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 |  | 
 | 281 | def 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 |