| #!/usr/bin/env python3 | 
 |  | 
 | r""" | 
 | See help text for details. | 
 | """ | 
 |  | 
 | import os | 
 | import subprocess | 
 | import sys | 
 |  | 
 | 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:               <failed plug-in value," | 
 |     + " if any>\n  shell_rc:                          " | 
 |     + "<shell return code value of last call point program - this" | 
 |     + " will be printed in hexadecimal format.  Also, be aware" | 
 |     + " that if a call point program returns a value it will be" | 
 |     + " shifted left 2 bytes (e.g. rc of 2 will be printed as" | 
 |     + " 0x00000200).  That is because the rightmost byte is" | 
 |     + " reserved for errors in calling the call point program" | 
 |     + " rather than errors generated by the call point program.>", | 
 |     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() |