#!/usr/bin/env python r""" See help text for details. """ import sys import subprocess import os save_dir_path = sys.path.pop(0) modules = ['gen_arg', 'gen_print', 'gen_valid', 'gen_plug_in', 'gen_cmd', 'gen_misc'] for module in modules: exec("from " + module + " import *") sys.path.insert(0, save_dir_path) # Create parser object. parser = argparse.ArgumentParser( usage='%(prog)s [OPTIONS]', description="%(prog)s will process the plug-in packages passed to it." + " A plug-in package is essentially a directory containing" + " one or more call point programs. Each of these call point" + " programs must have a prefix of \"cp_\". When calling" + " %(prog)s, a user must provide a call_point parameter" + " (described below). For each plug-in package passed," + " %(prog)s will check for the presence of the specified call" + " point program in the plug-in directory. If it is found," + " %(prog)s will run it. It is the responsibility of the" + " caller to set any environment variables needed by the call" + " point programs.\n\nAfter each call point program" + " has been run, %(prog)s will print the following values in" + " the following formats for use by the calling program:\n" + " failed_plug_in_name: \n shell_rc: " + "", formatter_class=argparse.ArgumentDefaultsHelpFormatter, prefix_chars='-+') # Create arguments. parser.add_argument( 'plug_in_dir_paths', nargs='?', default="", help=plug_in_dir_paths_help_text + default_string) parser.add_argument( '--call_point', default="setup", required=True, help='The call point program name. This value must not include the' + ' "cp_" prefix. For each plug-in package passed to this program,' + ' the specified call_point program will be called if it exists in' + ' the plug-in directory.' + default_string) parser.add_argument( '--allow_shell_rc', default="0x00000000", help='The user may supply a value other than zero to indicate an' + ' acceptable non-zero return code. For example, if this value' + ' equals 0x00000200, it means that for each plug-in call point that' + ' runs, a 0x00000200 will not be counted as a failure. See note' + ' above regarding left-shifting of return codes.' + default_string) parser.add_argument( '--stop_on_plug_in_failure', default=1, type=int, choices=[1, 0], help='If this parameter is set to 1, this program will stop and return ' + 'non-zero if the call point program from any plug-in directory ' + 'fails. Conversely, if it is set to false, this program will run ' + 'the call point program from each and every plug-in directory ' + 'regardless of their return values. Typical example cases where ' + 'you\'d want to run all plug-in call points regardless of success ' + 'or failure would be "cleanup" or "ffdc" call points.') parser.add_argument( '--stop_on_non_zero_rc', default=0, type=int, choices=[1, 0], help='If this parm is set to 1 and a plug-in call point program returns ' + 'a valid non-zero return code (see "allow_shell_rc" parm above),' + ' this program will stop processing and return 0 (success). Since' + ' this constitutes a successful exit, this would normally be used' + ' where the caller wishes to stop processing if one of the plug-in' + ' directory call point programs returns a special value indicating' + ' that some special case has been found. An example might be in' + ' calling some kind of "check_errl" call point program. Such a' + ' call point program might return a 2 (i.e. 0x00000200) to indicate' + ' that a given error log entry was found in an "ignore" list and is' + ' therefore to be ignored. That being the case, no other' + ' "check_errl" call point program would need to be called.' + default_string) parser.add_argument( '--mch_class', default="obmc", help=mch_class_help_text + default_string) # Populate stock_list with options we want. stock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)] original_path = os.environ.get('PATH') def validate_parms(): r""" Validate program parameters, etc. Return True or False accordingly. """ valid_value(call_point) global allow_shell_rc valid_integer(allow_shell_rc) # Convert to hex string for consistency in printout. allow_shell_rc = "0x%08x" % int(allow_shell_rc, 0) set_pgm_arg(allow_shell_rc) def run_pgm(plug_in_dir_path, call_point, allow_shell_rc): r""" Run the call point program in the given plug_in_dir_path. Return the following: rc The return code - 0 = PASS, 1 = FAIL. shell_rc The shell return code returned by process_plug_in_packages.py. failed_plug_in_name The failed plug in name (if any). Description of arguments: plug_in_dir_path The directory path where the call_point program may be located. call_point The call point (e.g. "setup"). This program will look for a program named "cp_" + call_point in the plug_in_dir_path. If no such call point program is found, this function returns an rc of 0 (i.e. success). allow_shell_rc The user may supply a value other than zero to indicate an acceptable non-zero return code. For example, if this value equals 0x00000200, it means that for each plug-in call point that runs, a 0x00000200 will not be counted as a failure. See note above regarding left-shifting of return codes. """ rc = 0 failed_plug_in_name = "" shell_rc = 0x00000000 plug_in_name = os.path.basename(os.path.normpath(plug_in_dir_path)) cp_prefix = "cp_" plug_in_pgm_path = plug_in_dir_path + cp_prefix + call_point if not os.path.exists(plug_in_pgm_path): # No such call point in this plug in dir path. This is legal so we return 0, etc. return rc, shell_rc, failed_plug_in_name print("------------------------------------------------- Starting plug-" + "in -----------------------------------------------") print_timen("Running " + plug_in_name + "/" + cp_prefix + call_point + ".") stdout = 1 - quiet if AUTOBOOT_OPENBMC_NICKNAME != "": auto_status_file_prefix = AUTOBOOT_OPENBMC_NICKNAME + "." else: auto_status_file_prefix = "" auto_status_file_prefix += plug_in_name + ".cp_" + call_point status_dir_path =\ add_trailing_slash(os.environ.get("STATUS_DIR_PATH", os.environ['HOME'] + "/status/")) if not os.path.isdir(status_dir_path): AUTOBOOT_EXECDIR = \ add_trailing_slash(os.environ.get("AUTOBOOT_EXECDIR", "")) status_dir_path = AUTOBOOT_EXECDIR + "logs/" if not os.path.exists(status_dir_path): os.makedirs(status_dir_path) status_file_name = auto_status_file_prefix + "." + file_date_time_stamp() \ + ".status" auto_status_file_subcmd = "auto_status_file.py --status_dir_path=" \ + status_dir_path + " --status_file_name=" + status_file_name \ + " --quiet=1 --show_url=1 --prefix=" \ + auto_status_file_prefix + " --stdout=" + str(stdout) + " " cmd_buf = "PATH=" + plug_in_dir_path.rstrip("/") + ":${PATH}" print_issuing(cmd_buf) os.environ['PATH'] = plug_in_dir_path.rstrip("/") + os.pathsep + original_path cmd_buf = auto_status_file_subcmd + cp_prefix + call_point print_issuing(cmd_buf) sub_proc = subprocess.Popen(cmd_buf, shell=True) sub_proc.communicate() shell_rc = sub_proc.returncode # Shift to left. shell_rc *= 0x100 if shell_rc != 0 and shell_rc != allow_shell_rc: rc = 1 failed_plug_in_name = plug_in_name + "/" + cp_prefix + call_point if shell_rc != 0: failed_plug_in_name = plug_in_name + "/" + cp_prefix + call_point if failed_plug_in_name != "" and not stdout: # Use tail to avoid double-printing of status_file_url. shell_cmd("tail -n +2 " + status_dir_path + status_file_name, quiet=1, print_output=1) print("------------------------------------------------- Ending plug-in" + " -------------------------------------------------") if failed_plug_in_name != "": print_var(failed_plug_in_name) print_var(shell_rc, hexa()) return rc, shell_rc, failed_plug_in_name def main(): gen_setup() set_term_options(term_requests='children') # Access program parameter globals. global plug_in_dir_paths global mch_class global allow_shell_rc global stop_on_plug_in_failure global stop_on_non_zero_rc plug_in_packages_list = return_plug_in_packages_list(plug_in_dir_paths, mch_class) qprint_var(plug_in_packages_list) qprint("\n") allow_shell_rc = int(allow_shell_rc, 0) shell_rc = 0 failed_plug_in_name = "" global AUTOBOOT_OPENBMC_NICKNAME AUTOBOOT_OPENBMC_NICKNAME = os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "") ret_code = 0 for plug_in_dir_path in plug_in_packages_list: rc, shell_rc, failed_plug_in_name = \ run_pgm(plug_in_dir_path, call_point, allow_shell_rc) if rc != 0: ret_code = 1 if stop_on_plug_in_failure: break if shell_rc != 0 and stop_on_non_zero_rc: qprint_time("Stopping on non-zero shell return code as requested" + " by caller.\n") break if ret_code != 0: print_error("At least one plug-in failed.\n") exit(1) main()