1e7e9171eSGeorge Keishing#!/usr/bin/env python3 27423c01aSMichael Walsh 360d08f3dSMichael Walshr""" 460d08f3dSMichael WalshSee help text for details. 560d08f3dSMichael Walsh""" 660d08f3dSMichael Walsh 7e635ddc0SGeorge Keishingimport os 8*20f38712SPatrick Williamsimport subprocess 9*20f38712SPatrick Williamsimport sys 107423c01aSMichael Walsh 1160d08f3dSMichael Walshsave_dir_path = sys.path.pop(0) 127423c01aSMichael Walsh 13*20f38712SPatrick Williamsmodules = [ 14*20f38712SPatrick Williams "gen_arg", 15*20f38712SPatrick Williams "gen_print", 16*20f38712SPatrick Williams "gen_valid", 17*20f38712SPatrick Williams "gen_plug_in", 18*20f38712SPatrick Williams "gen_cmd", 19*20f38712SPatrick Williams "gen_misc", 20*20f38712SPatrick Williams] 2160d08f3dSMichael Walshfor module in modules: 2260d08f3dSMichael Walsh exec("from " + module + " import *") 237423c01aSMichael Walsh 2460d08f3dSMichael Walshsys.path.insert(0, save_dir_path) 257423c01aSMichael Walsh 267423c01aSMichael Walsh# Create parser object. 277423c01aSMichael Walshparser = argparse.ArgumentParser( 28*20f38712SPatrick Williams usage="%(prog)s [OPTIONS]", 29004ad3c9SJoy Onyerikwu description="%(prog)s will process the plug-in packages passed to it." 30004ad3c9SJoy Onyerikwu + " A plug-in package is essentially a directory containing" 31004ad3c9SJoy Onyerikwu + " one or more call point programs. Each of these call point" 32*20f38712SPatrick Williams + ' programs must have a prefix of "cp_". When calling' 33004ad3c9SJoy Onyerikwu + " %(prog)s, a user must provide a call_point parameter" 34004ad3c9SJoy Onyerikwu + " (described below). For each plug-in package passed," 35004ad3c9SJoy Onyerikwu + " %(prog)s will check for the presence of the specified call" 36004ad3c9SJoy Onyerikwu + " point program in the plug-in directory. If it is found," 37004ad3c9SJoy Onyerikwu + " %(prog)s will run it. It is the responsibility of the" 38004ad3c9SJoy Onyerikwu + " caller to set any environment variables needed by the call" 39004ad3c9SJoy Onyerikwu + " point programs.\n\nAfter each call point program" 40004ad3c9SJoy Onyerikwu + " has been run, %(prog)s will print the following values in" 41004ad3c9SJoy Onyerikwu + " the following formats for use by the calling program:\n" 42004ad3c9SJoy Onyerikwu + " failed_plug_in_name: <failed plug-in value," 43004ad3c9SJoy Onyerikwu + " if any>\n shell_rc: " 44004ad3c9SJoy Onyerikwu + "<shell return code value of last call point program - this" 45004ad3c9SJoy Onyerikwu + " will be printed in hexadecimal format. Also, be aware" 46004ad3c9SJoy Onyerikwu + " that if a call point program returns a value it will be" 47004ad3c9SJoy Onyerikwu + " shifted left 2 bytes (e.g. rc of 2 will be printed as" 48004ad3c9SJoy Onyerikwu + " 0x00000200). That is because the rightmost byte is" 49004ad3c9SJoy Onyerikwu + " reserved for errors in calling the call point program" 50004ad3c9SJoy Onyerikwu + " rather than errors generated by the call point program.>", 51d0741f8aSMichael Walsh formatter_class=argparse.ArgumentDefaultsHelpFormatter, 52*20f38712SPatrick Williams prefix_chars="-+", 53*20f38712SPatrick Williams) 547423c01aSMichael Walsh 557423c01aSMichael Walsh# Create arguments. 567423c01aSMichael Walshparser.add_argument( 57*20f38712SPatrick Williams "plug_in_dir_paths", 58*20f38712SPatrick Williams nargs="?", 597423c01aSMichael Walsh default="", 60*20f38712SPatrick Williams help=plug_in_dir_paths_help_text + default_string, 61*20f38712SPatrick Williams) 627423c01aSMichael Walsh 637423c01aSMichael Walshparser.add_argument( 64*20f38712SPatrick Williams "--call_point", 657423c01aSMichael Walsh default="setup", 667423c01aSMichael Walsh required=True, 67*20f38712SPatrick Williams help="The call point program name. This value must not include the" 68004ad3c9SJoy Onyerikwu + ' "cp_" prefix. For each plug-in package passed to this program,' 69*20f38712SPatrick Williams + " the specified call_point program will be called if it exists in" 70*20f38712SPatrick Williams + " the plug-in directory." 71*20f38712SPatrick Williams + default_string, 72*20f38712SPatrick Williams) 737423c01aSMichael Walsh 747423c01aSMichael Walshparser.add_argument( 75*20f38712SPatrick Williams "--allow_shell_rc", 767423c01aSMichael Walsh default="0x00000000", 77*20f38712SPatrick Williams help="The user may supply a value other than zero to indicate an" 78*20f38712SPatrick Williams + " acceptable non-zero return code. For example, if this value" 79*20f38712SPatrick Williams + " equals 0x00000200, it means that for each plug-in call point that" 80*20f38712SPatrick Williams + " runs, a 0x00000200 will not be counted as a failure. See note" 81*20f38712SPatrick Williams + " above regarding left-shifting of return codes." 82*20f38712SPatrick Williams + default_string, 83*20f38712SPatrick Williams) 847423c01aSMichael Walsh 857423c01aSMichael Walshparser.add_argument( 86*20f38712SPatrick Williams "--stop_on_plug_in_failure", 877423c01aSMichael Walsh default=1, 887423c01aSMichael Walsh type=int, 897423c01aSMichael Walsh choices=[1, 0], 90*20f38712SPatrick Williams help="If this parameter is set to 1, this program will stop and return " 91*20f38712SPatrick Williams + "non-zero if the call point program from any plug-in directory " 92*20f38712SPatrick Williams + "fails. Conversely, if it is set to false, this program will run " 93*20f38712SPatrick Williams + "the call point program from each and every plug-in directory " 94*20f38712SPatrick Williams + "regardless of their return values. Typical example cases where " 95*20f38712SPatrick Williams + "you'd want to run all plug-in call points regardless of success " 96*20f38712SPatrick Williams + 'or failure would be "cleanup" or "ffdc" call points.', 97*20f38712SPatrick Williams) 987423c01aSMichael Walsh 997423c01aSMichael Walshparser.add_argument( 100*20f38712SPatrick Williams "--stop_on_non_zero_rc", 1017423c01aSMichael Walsh default=0, 1027423c01aSMichael Walsh type=int, 1037423c01aSMichael Walsh choices=[1, 0], 104*20f38712SPatrick Williams help="If this parm is set to 1 and a plug-in call point program returns " 105004ad3c9SJoy Onyerikwu + 'a valid non-zero return code (see "allow_shell_rc" parm above),' 106*20f38712SPatrick Williams + " this program will stop processing and return 0 (success). Since" 107*20f38712SPatrick Williams + " this constitutes a successful exit, this would normally be used" 108*20f38712SPatrick Williams + " where the caller wishes to stop processing if one of the plug-in" 109*20f38712SPatrick Williams + " directory call point programs returns a special value indicating" 110*20f38712SPatrick Williams + " that some special case has been found. An example might be in" 111004ad3c9SJoy Onyerikwu + ' calling some kind of "check_errl" call point program. Such a' 112*20f38712SPatrick Williams + " call point program might return a 2 (i.e. 0x00000200) to indicate" 113004ad3c9SJoy Onyerikwu + ' that a given error log entry was found in an "ignore" list and is' 114*20f38712SPatrick Williams + " therefore to be ignored. That being the case, no other" 115004ad3c9SJoy Onyerikwu + ' "check_errl" call point program would need to be called.' 116*20f38712SPatrick Williams + default_string, 117*20f38712SPatrick Williams) 1187423c01aSMichael Walsh 1197423c01aSMichael Walshparser.add_argument( 120*20f38712SPatrick Williams "--mch_class", default="obmc", help=mch_class_help_text + default_string 121*20f38712SPatrick Williams) 1227423c01aSMichael Walsh 12360d08f3dSMichael Walsh# Populate stock_list with options we want. 1247423c01aSMichael Walshstock_list = [("test_mode", 0), ("quiet", 1), ("debug", 0)] 1257423c01aSMichael Walsh 126*20f38712SPatrick Williamsoriginal_path = os.environ.get("PATH") 127de093d20SMichael Walsh 1287423c01aSMichael Walsh 1297423c01aSMichael Walshdef validate_parms(): 1307423c01aSMichael Walsh r""" 1317423c01aSMichael Walsh Validate program parameters, etc. Return True or False accordingly. 1327423c01aSMichael Walsh """ 1337423c01aSMichael Walsh 13460d08f3dSMichael Walsh valid_value(call_point) 1357423c01aSMichael Walsh 136ed18ec7aSMichael Walsh global allow_shell_rc 13760d08f3dSMichael Walsh valid_integer(allow_shell_rc) 138c33ef37aSMichael Walsh 139c33ef37aSMichael Walsh # Convert to hex string for consistency in printout. 140ed18ec7aSMichael Walsh allow_shell_rc = "0x%08x" % int(allow_shell_rc, 0) 141ed18ec7aSMichael Walsh set_pgm_arg(allow_shell_rc) 142c33ef37aSMichael Walsh 1437423c01aSMichael Walsh 144*20f38712SPatrick Williamsdef run_pgm(plug_in_dir_path, call_point, allow_shell_rc): 1457423c01aSMichael Walsh r""" 146410b1787SMichael Walsh Run the call point program in the given plug_in_dir_path. Return the following: 1477423c01aSMichael Walsh rc The return code - 0 = PASS, 1 = FAIL. 148410b1787SMichael Walsh shell_rc The shell return code returned by process_plug_in_packages.py. 1497423c01aSMichael Walsh failed_plug_in_name The failed plug in name (if any). 1507423c01aSMichael Walsh 1517423c01aSMichael Walsh Description of arguments: 152410b1787SMichael Walsh plug_in_dir_path The directory path where the call_point program may be located. 153410b1787SMichael Walsh call_point The call point (e.g. "setup"). This program will look for a program 154410b1787SMichael Walsh named "cp_" + call_point in the plug_in_dir_path. If no such call point 155410b1787SMichael Walsh program is found, this function returns an rc of 0 (i.e. success). 156410b1787SMichael Walsh allow_shell_rc The user may supply a value other than zero to indicate an acceptable 157410b1787SMichael Walsh non-zero return code. For example, if this value equals 0x00000200, it 158410b1787SMichael Walsh means that for each plug-in call point that runs, a 0x00000200 will not 159410b1787SMichael Walsh be counted as a failure. See note above regarding left-shifting of 1607423c01aSMichael Walsh return codes. 1617423c01aSMichael Walsh """ 1627423c01aSMichael Walsh 1637423c01aSMichael Walsh rc = 0 1647423c01aSMichael Walsh failed_plug_in_name = "" 1657423c01aSMichael Walsh shell_rc = 0x00000000 1667423c01aSMichael Walsh 16797d5b363SMichael Walsh plug_in_name = os.path.basename(os.path.normpath(plug_in_dir_path)) 1687423c01aSMichael Walsh cp_prefix = "cp_" 1697423c01aSMichael Walsh plug_in_pgm_path = plug_in_dir_path + cp_prefix + call_point 1707423c01aSMichael Walsh if not os.path.exists(plug_in_pgm_path): 171410b1787SMichael Walsh # No such call point in this plug in dir path. This is legal so we return 0, etc. 1727423c01aSMichael Walsh return rc, shell_rc, failed_plug_in_name 1737423c01aSMichael Walsh 174*20f38712SPatrick Williams print( 175*20f38712SPatrick Williams "------------------------------------------------- Starting plug-" 176*20f38712SPatrick Williams + "in -----------------------------------------------" 177*20f38712SPatrick Williams ) 1788c5a8a8dSMichael Walsh 1798c5a8a8dSMichael Walsh print_timen("Running " + plug_in_name + "/" + cp_prefix + call_point + ".") 180b3beaa84SMichael Walsh 18197d5b363SMichael Walsh stdout = 1 - quiet 18297d5b363SMichael Walsh if AUTOBOOT_OPENBMC_NICKNAME != "": 183b3beaa84SMichael Walsh auto_status_file_prefix = AUTOBOOT_OPENBMC_NICKNAME + "." 18497d5b363SMichael Walsh else: 185b3beaa84SMichael Walsh auto_status_file_prefix = "" 186b3beaa84SMichael Walsh auto_status_file_prefix += plug_in_name + ".cp_" + call_point 187*20f38712SPatrick Williams status_dir_path = add_trailing_slash( 188*20f38712SPatrick Williams os.environ.get("STATUS_DIR_PATH", os.environ["HOME"] + "/status/") 189*20f38712SPatrick Williams ) 1900a3bdb4cSMichael Walsh if not os.path.isdir(status_dir_path): 191*20f38712SPatrick Williams AUTOBOOT_EXECDIR = add_trailing_slash( 192*20f38712SPatrick Williams os.environ.get("AUTOBOOT_EXECDIR", "") 193*20f38712SPatrick Williams ) 1940a3bdb4cSMichael Walsh status_dir_path = AUTOBOOT_EXECDIR + "logs/" 1950a3bdb4cSMichael Walsh if not os.path.exists(status_dir_path): 1960a3bdb4cSMichael Walsh os.makedirs(status_dir_path) 197*20f38712SPatrick Williams status_file_name = ( 198*20f38712SPatrick Williams auto_status_file_prefix + "." + file_date_time_stamp() + ".status" 199*20f38712SPatrick Williams ) 200*20f38712SPatrick Williams auto_status_file_subcmd = ( 201*20f38712SPatrick Williams "auto_status_file.py --status_dir_path=" 202*20f38712SPatrick Williams + status_dir_path 203*20f38712SPatrick Williams + " --status_file_name=" 204*20f38712SPatrick Williams + status_file_name 205*20f38712SPatrick Williams + " --quiet=1 --show_url=1 --prefix=" 206*20f38712SPatrick Williams + auto_status_file_prefix 207*20f38712SPatrick Williams + " --stdout=" 208*20f38712SPatrick Williams + str(stdout) 209*20f38712SPatrick Williams + " " 210*20f38712SPatrick Williams ) 21197d5b363SMichael Walsh 212de093d20SMichael Walsh cmd_buf = "PATH=" + plug_in_dir_path.rstrip("/") + ":${PATH}" 213de093d20SMichael Walsh print_issuing(cmd_buf) 214*20f38712SPatrick Williams os.environ["PATH"] = ( 215*20f38712SPatrick Williams plug_in_dir_path.rstrip("/") + os.pathsep + original_path 216*20f38712SPatrick Williams ) 217de093d20SMichael Walsh cmd_buf = auto_status_file_subcmd + cp_prefix + call_point 2188c5a8a8dSMichael Walsh print_issuing(cmd_buf) 2197423c01aSMichael Walsh 220be6153b8SMichael Walsh sub_proc = subprocess.Popen(cmd_buf, shell=True) 221be6153b8SMichael Walsh sub_proc.communicate() 2227423c01aSMichael Walsh shell_rc = sub_proc.returncode 223c33ef37aSMichael Walsh # Shift to left. 224c33ef37aSMichael Walsh shell_rc *= 0x100 225ed18ec7aSMichael Walsh if shell_rc != 0 and shell_rc != allow_shell_rc: 2267423c01aSMichael Walsh rc = 1 2278c5a8a8dSMichael Walsh failed_plug_in_name = plug_in_name + "/" + cp_prefix + call_point 2283ba8ecdcSMichael Walsh if shell_rc != 0: 2298c5a8a8dSMichael Walsh failed_plug_in_name = plug_in_name + "/" + cp_prefix + call_point 230b3beaa84SMichael Walsh if failed_plug_in_name != "" and not stdout: 231b3beaa84SMichael Walsh # Use tail to avoid double-printing of status_file_url. 232*20f38712SPatrick Williams shell_cmd( 233*20f38712SPatrick Williams "tail -n +2 " + status_dir_path + status_file_name, 234*20f38712SPatrick Williams quiet=1, 235*20f38712SPatrick Williams print_output=1, 236*20f38712SPatrick Williams ) 2377423c01aSMichael Walsh 238*20f38712SPatrick Williams print( 239*20f38712SPatrick Williams "------------------------------------------------- Ending plug-in" 240*20f38712SPatrick Williams + " -------------------------------------------------" 241*20f38712SPatrick Williams ) 24297d5b363SMichael Walsh if failed_plug_in_name != "": 24397d5b363SMichael Walsh print_var(failed_plug_in_name) 2440d5f96a4SMichael Walsh print_var(shell_rc, hexa()) 2457423c01aSMichael Walsh 2467423c01aSMichael Walsh return rc, shell_rc, failed_plug_in_name 2477423c01aSMichael Walsh 2487423c01aSMichael Walsh 2497423c01aSMichael Walshdef main(): 25060d08f3dSMichael Walsh gen_setup() 2517423c01aSMichael Walsh 252*20f38712SPatrick Williams set_term_options(term_requests="children") 253de093d20SMichael Walsh 2547423c01aSMichael Walsh # Access program parameter globals. 2557423c01aSMichael Walsh global plug_in_dir_paths 2567423c01aSMichael Walsh global mch_class 257ed18ec7aSMichael Walsh global allow_shell_rc 2587423c01aSMichael Walsh global stop_on_plug_in_failure 2597423c01aSMichael Walsh global stop_on_non_zero_rc 2607423c01aSMichael Walsh 261*20f38712SPatrick Williams plug_in_packages_list = return_plug_in_packages_list( 262*20f38712SPatrick Williams plug_in_dir_paths, mch_class 263*20f38712SPatrick Williams ) 2647423c01aSMichael Walsh 2650d5f96a4SMichael Walsh qprint_var(plug_in_packages_list) 2667423c01aSMichael Walsh qprint("\n") 2677423c01aSMichael Walsh 268ed18ec7aSMichael Walsh allow_shell_rc = int(allow_shell_rc, 0) 269a6723f27SMichael Walsh shell_rc = 0 2707423c01aSMichael Walsh failed_plug_in_name = "" 2717423c01aSMichael Walsh 27297d5b363SMichael Walsh global AUTOBOOT_OPENBMC_NICKNAME 273b3beaa84SMichael Walsh AUTOBOOT_OPENBMC_NICKNAME = os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "") 274b3beaa84SMichael Walsh 2757423c01aSMichael Walsh ret_code = 0 2767423c01aSMichael Walsh for plug_in_dir_path in plug_in_packages_list: 277*20f38712SPatrick Williams rc, shell_rc, failed_plug_in_name = run_pgm( 278*20f38712SPatrick Williams plug_in_dir_path, call_point, allow_shell_rc 279*20f38712SPatrick Williams ) 2807423c01aSMichael Walsh if rc != 0: 2817423c01aSMichael Walsh ret_code = 1 2827423c01aSMichael Walsh if stop_on_plug_in_failure: 2837423c01aSMichael Walsh break 2847423c01aSMichael Walsh if shell_rc != 0 and stop_on_non_zero_rc: 285*20f38712SPatrick Williams qprint_time( 286*20f38712SPatrick Williams "Stopping on non-zero shell return code as requested" 287*20f38712SPatrick Williams + " by caller.\n" 288*20f38712SPatrick Williams ) 2897423c01aSMichael Walsh break 2907423c01aSMichael Walsh 29160d08f3dSMichael Walsh if ret_code != 0: 29297d5b363SMichael Walsh print_error("At least one plug-in failed.\n") 2937423c01aSMichael Walsh exit(1) 29460d08f3dSMichael Walsh 29560d08f3dSMichael Walsh 29660d08f3dSMichael Walshmain() 297