1#!/usr/bin/env python3 2 3r""" 4This module provides functions which are useful for running plug-ins. 5""" 6 7import glob 8import os 9import sys 10 11import gen_misc as gm 12import gen_print as gp 13 14# Some help text that is common to more than one program. 15plug_in_dir_paths_help_text = ( 16 "This is a colon-separated list of plug-in directory paths. If one" 17 + " of the entries in the list is a plain directory name (i.e. no" 18 + " path info), it will be taken to be a native plug-in. In that case," 19 + ' %(prog)s will search for the native plug-in in the "plug-ins"' 20 + " subdirectory of each path in the PATH environment variable until it" 21 + " is found. Also, integrated plug-ins will automatically be appended" 22 + " to your plug_in_dir_paths list. An integrated plug-in is any plug-in" 23 + ' found using the PATH variable that contains a file named "integrated".' 24) 25 26mch_class_help_text = ( 27 'The class of machine that we are testing (e.g. "op" = "open power",' 28 + ' "obmc" = "open bmc", etc).' 29) 30 31PATH_LIST = gm.return_path_list() 32 33 34def get_plug_in_base_paths(): 35 r""" 36 Get plug-in base paths and return them as a list. 37 38 This function searches the PATH_LIST (created from PATH environment variable) for any paths that have a 39 "plug_ins" subdirectory. All such paths are considered plug_in_base paths. 40 """ 41 42 global PATH_LIST 43 44 plug_in_base_path_list = [] 45 46 for path in PATH_LIST: 47 candidate_plug_in_base_path = path + "plug_ins/" 48 if os.path.isdir(candidate_plug_in_base_path): 49 plug_in_base_path_list.append(candidate_plug_in_base_path) 50 51 return plug_in_base_path_list 52 53 54# Define global plug_in_base_path_list and call get_plug_in_base_paths to set its value. 55plug_in_base_path_list = get_plug_in_base_paths() 56 57 58def find_plug_in_package(plug_in_name): 59 r""" 60 Find and return the normalized directory path of the specified plug in. This is done by searching the 61 global plug_in_base_path_list. 62 63 Description of arguments: 64 plug_in_name The unqualified name of the plug-in package. 65 """ 66 67 global plug_in_base_path_list 68 for plug_in_base_dir_path in plug_in_base_path_list: 69 candidate_plug_in_dir_path = ( 70 os.path.normpath(plug_in_base_dir_path + plug_in_name) + os.sep 71 ) 72 if os.path.isdir(candidate_plug_in_dir_path): 73 return candidate_plug_in_dir_path 74 75 return "" 76 77 78def validate_plug_in_package(plug_in_dir_path, mch_class="obmc"): 79 r""" 80 Validate the plug in package and return the normalized plug-in directory path. 81 82 Description of arguments: 83 plug_in_dir_path The "relative" or absolute path to a plug in package directory. 84 mch_class The class of machine that we are testing (e.g. "op" = "open power", 85 "obmc" = "open bmc", etc). 86 """ 87 88 gp.dprint_executing() 89 90 if os.path.isabs(plug_in_dir_path): 91 # plug_in_dir_path begins with a slash so it is an absolute path. 92 candidate_plug_in_dir_path = ( 93 os.path.normpath(plug_in_dir_path) + os.sep 94 ) 95 if not os.path.isdir(candidate_plug_in_dir_path): 96 gp.print_error_report( 97 'Plug-in directory path "' 98 + plug_in_dir_path 99 + '" does not exist.\n' 100 ) 101 exit(1) 102 else: 103 # The plug_in_dir_path is actually a simple name (e.g. "OBMC_Sample")... 104 candidate_plug_in_dir_path = find_plug_in_package(plug_in_dir_path) 105 if candidate_plug_in_dir_path == "": 106 global PATH_LIST 107 gp.print_error_report( 108 'Plug-in directory path "' 109 + plug_in_dir_path 110 + '" could not be found' 111 + " in any of the following directories:\n" 112 + gp.sprint_var(PATH_LIST) 113 ) 114 exit(1) 115 # Make sure that this plug-in supports us... 116 supports_file_path = candidate_plug_in_dir_path + "supports_" + mch_class 117 if not os.path.exists(supports_file_path): 118 gp.print_error_report( 119 "The following file path could not be" 120 + " found:\n" 121 + gp.sprint_varx("supports_file_path", supports_file_path) 122 + "\nThis file is necessary to indicate that" 123 + " the given plug-in supports the class of" 124 + ' machine we are testing, namely "' 125 + mch_class 126 + '".\n' 127 ) 128 exit(1) 129 130 return candidate_plug_in_dir_path 131 132 133def return_integrated_plug_ins(mch_class="obmc"): 134 r""" 135 Return a list of integrated plug-ins. Integrated plug-ins are plug-ins which are selected without regard 136 for whether the user has specified them. In other words, they are "integrated" into the program suite. 137 The programmer designates a plug-in as integrated by putting a file named "integrated" into the plug-in 138 package directory. 139 140 Description of arguments: 141 mch_class The class of machine that we are testing (e.g. "op" = "open power", 142 "obmc" = "open bmc", etc). 143 """ 144 145 global plug_in_base_path_list 146 147 integrated_plug_ins_list = [] 148 149 DEBUG_SKIP_INTEGRATED = int(os.getenv("DEBUG_SKIP_INTEGRATED", "0")) 150 151 if DEBUG_SKIP_INTEGRATED: 152 return integrated_plug_ins_list 153 154 for plug_in_base_path in plug_in_base_path_list: 155 # Get a list of all plug-in paths that support our mch_class. 156 mch_class_candidate_list = glob.glob( 157 plug_in_base_path + "*/supports_" + mch_class 158 ) 159 for candidate_path in mch_class_candidate_list: 160 integrated_plug_in_dir_path = ( 161 os.path.dirname(candidate_path) + os.sep 162 ) 163 integrated_file_path = integrated_plug_in_dir_path + "integrated" 164 if os.path.exists(integrated_file_path): 165 plug_in_name = os.path.basename( 166 os.path.dirname(candidate_path) 167 ) 168 if plug_in_name not in integrated_plug_ins_list: 169 # If this plug-in has not already been added to the list... 170 integrated_plug_ins_list.append(plug_in_name) 171 172 return integrated_plug_ins_list 173 174 175def return_plug_in_packages_list(plug_in_dir_paths, mch_class="obmc"): 176 r""" 177 Return a list of plug-in packages given the plug_in_dir_paths string. This function calls 178 validate_plug_in_package so it will fail if plug_in_dir_paths contains any invalid plug-ins. 179 180 Description of arguments: 181 plug_in_dir_path The "relative" or absolute path to a plug in package directory. 182 mch_class The class of machine that we are testing (e.g. "op" = "open power", 183 "obmc" = "open bmc", etc). 184 """ 185 186 if plug_in_dir_paths != "": 187 plug_in_packages_list = plug_in_dir_paths.split(":") 188 else: 189 plug_in_packages_list = [] 190 191 # Get a list of integrated plug-ins (w/o full path names). 192 integrated_plug_ins_list = return_integrated_plug_ins(mch_class) 193 # Put both lists together in plug_in_packages_list with no duplicates. NOTE: This won't catch 194 # duplicates if the caller specifies the full path name of a native plug-in but that should be rare 195 # enough. 196 197 plug_in_packages_list = plug_in_packages_list + integrated_plug_ins_list 198 199 plug_in_packages_list = list( 200 set( 201 [ 202 validate_plug_in_package(path, mch_class) 203 for path in plug_in_packages_list 204 ] 205 ) 206 ) 207 208 return plug_in_packages_list 209