1#!/usr/bin/env python 2 3r""" 4This module provides functions which are useful to plug-in call point programs. 5""" 6 7import sys 8import os 9import re 10import collections 11 12import gen_print as gp 13import gen_misc as gm 14 15 16def get_plug_in_package_name(case=None): 17 r""" 18 Return the plug-in package name (e.g. "OS_Console", "DB_Logging"). 19 20 Description of argument(s): 21 case Indicates whether the value returned 22 should be converted to upper or lower 23 case. Valid values are "upper", "lower" 24 or None. 25 """ 26 27 plug_in_package_name = os.path.basename(gp.pgm_dir_path[:-1]) 28 if case == "upper": 29 return plug_in_package_name.upper() 30 elif case == "lower": 31 return plug_in_package_name.lower() 32 else: 33 return plug_in_package_name 34 35 36def return_plug_vars(): 37 r""" 38 Return an OrderedDict which is sorted by key and which contains all of the 39 plug-in environment variables. 40 41 Example excerpt of resulting dictionary: 42 43 plug_var_dict: 44 [AUTOBOOT_BASE_TOOL_DIR_PATH]: /fspmount/ 45 [AUTOBOOT_BB_LEVEL]: <blank> 46 [AUTOBOOT_BOOT_FAIL]: 0 47 ... 48 49 This function also does the following: 50 - Set a default value for environment variable AUTOBOOT_OPENBMC_NICKNAME 51 if it is not already set. 52 - Register PASSWORD variables to prevent their values from being printed. 53 """ 54 55 plug_in_package_name = get_plug_in_package_name(case="upper") 56 regex = "^(AUTOBOOT|AUTOGUI|" + plug_in_package_name + ")_" 57 58 # Set a default for nickname. 59 if os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "") == "": 60 os.environ['AUTOBOOT_OPENBMC_NICKNAME'] = \ 61 os.environ.get("AUTOBOOT_OPENBMC_HOST", "") 62 63 # For all variables specified in the parm_def file, we want them to 64 # default to "" rather than being unset. 65 # Process the parm_def file if it exists. 66 parm_def_file_path = gp.pgm_dir_path + "parm_def" 67 if os.path.exists(parm_def_file_path): 68 parm_defs = gm.my_parm_file(parm_def_file_path) 69 else: 70 parm_defs = collections.OrderedDict() 71 # Example parm_defs: 72 # parm_defs: 73 # parm_defs[rest_fail]: boolean 74 # parm_defs[command]: string 75 # parm_defs[esel_stop_file_path]: string 76 77 # Create a list of plug-in environment variables by pre-pending <all caps 78 # plug-in package name>_<all caps var name> 79 plug_in_parm_names = [plug_in_package_name + "_" + x for x in 80 map(str.upper, parm_defs.keys())] 81 # Example plug_in_parm_names: 82 # plug_in_parm_names: 83 # plug_in_parm_names[0]: STOP_REST_FAIL 84 # plug_in_parm_names[1]: STOP_COMMAND 85 # plug_in_parm_names[2]: STOP_ESEL_STOP_FILE_PATH 86 87 # Initialize unset plug-in vars. 88 for var_name in plug_in_parm_names: 89 os.environ[var_name] = os.environ.get(var_name, "") 90 91 plug_var_dict = \ 92 collections.OrderedDict(sorted({k: v for (k, v) in 93 os.environ.items() 94 if re.match(regex, k)}.items())) 95 96 # Register password values to prevent printing them out. Any plug var 97 # whose name ends in PASSWORD will be registered. 98 password_vals = {k: v for (k, v) in plug_var_dict.items() 99 if re.match(r".*_PASSWORD$", k)}.values() 100 map(gp.register_passwords, password_vals) 101 102 return plug_var_dict 103 104 105def sprint_plug_vars(headers=1): 106 r""" 107 Sprint the plug-in environment variables (i.e. those that begin with 108 AUTOBOOT_ those that begin with <plug-in package_name>_ in upper case 109 letters.). 110 111 Example excerpt of output: 112 AUTOBOOT_BASE_TOOL_DIR_PATH=/fspmount/ 113 AUTOBOOT_BB_LEVEL= 114 AUTOBOOT_BOOT_FAIL=0 115 AUTOBOOT_BOOT_FAIL_THRESHOLD=1000000 116 117 Description of argument(s): 118 headers Print a header and a footer. 119 """ 120 121 plug_var_dict = return_plug_vars() 122 buffer = "" 123 if headers: 124 buffer += "\n" + gp.sprint_dashes() 125 for key, value in plug_var_dict.items(): 126 buffer += key + "=" + value + "\n" 127 if headers: 128 buffer += gp.sprint_dashes() + "\n" 129 130 return buffer 131 132 133def get_plug_vars(): 134 r""" 135 Get all plug-in variables and put them in corresponding global variables. 136 137 This would include all environment variables beginning with either 138 "AUTOBOOT_" or with the upper case version of the plug-in package name + 139 underscore (e.g. OP_SAMPLE_VAR1 for plug-in OP_Sample). 140 141 The global variables to be set will be both with and without the 142 "AUTOBOOT_" prefix. For example, if the environment variable in question 143 is AUTOBOOT_OPENBMC_HOST, this function will set global variable 144 AUTOBOOT_OPENBMC_HOST and global variable OPENBMC_HOST. 145 """ 146 147 module = sys.modules['__main__'] 148 plug_var_dict = return_plug_vars() 149 150 # Get all "AUTOBOOT_" environment variables and put them into globals. 151 for key, value in plug_var_dict.items(): 152 setattr(module, key, value) 153 setattr(module, re.sub("^AUTOBOOT_", "", key), value) 154 155 156def get_plug_default(var_name, 157 default=None): 158 r""" 159 Derive and return a default value for the given parm variable. 160 161 This function will assign a default by checking the following environment 162 variables in the order shown. The first one that has a value will be used. 163 - <upper case package_name>_<var_name> 164 - AUTOBOOT_OVERRIDE_<var_name> 165 - AUTOBOOT_<var_name> 166 167 If none of these are found, this function will return the value passed by 168 the caller in the "default" parm. 169 170 Example: 171 172 Let's say your plug-in is named "OS_Console" and you call this function as 173 follows: 174 175 get_plug_default("quiet", 0) 176 177 The first of these environment variables that is found to be set will be 178 used to provide the default value. 179 - OS_CONSOLE_QUIET 180 - AUTOBOOT_OVERRIDE_QUIET 181 - AUTOBOOT_QUIET 182 183 If none of those has a value, 0 (as specified by the caller in this 184 example) is returned. 185 186 Let's say the master driver program is named obmc_boot. obmc_boot program 187 is responsible for calling plug-ins. Let's further suppose that the user 188 wishes to run the master program with --debug=0 but wishes to have all 189 plug-ins run with --debug=1. This could be accomplished with the 190 following call: 191 export AUTOBOOT_OVERRIDE_DEBUG=1 ; obmc_boot --debug=0 192 --plug_in_dir_paths=<list of plug ins> 193 194 As another example, let's suppose that the user wishes to have just the 195 OS_Console plug-in run with debug and everything else to default to 196 debug=0. This could be accomplished as follows: 197 export OS_CONSOLE_DEBUG=1 ; obmc_boot --debug=0 --plug_in_dir_paths=<list 198 of plug ins> 199 200 And as one more example, let's say the user wishes to have obmc_boot and 201 OS_Console run without debug but have all other plug-ins run with debug: 202 export AUTOBOOT_OVERRIDE_DEBUG=1 ; export OS_CONSOLE_DEBUG=0 ; obmc_boot 203 --debug=0 --plug_in_dir_paths=<list of plug ins> 204 205 Description of argument(s): 206 var_name The name of the variable for which a 207 default value is to be calculated. 208 default The default value if one cannot be 209 determined. 210 """ 211 212 var_name = var_name.upper() 213 plug_in_package_name = get_plug_in_package_name(case="upper") 214 215 package_var_name = plug_in_package_name + "_" + var_name 216 default_value = os.environ.get(package_var_name, None) 217 if default_value is not None: 218 # A package-name version of the variable was found so return its value. 219 return(default_value) 220 221 autoboot_var_name = "AUTOBOOT_OVERRIDE_" + var_name 222 default_value = os.environ.get(autoboot_var_name, None) 223 if default_value is not None: 224 # An AUTOBOOT_ version of the variable was found so return its value. 225 return default_value 226 227 autoboot_var_name = "AUTOBOOT_" + var_name 228 default_value = os.environ.get(autoboot_var_name, None) 229 if default_value is not None: 230 # An AUTOBOOT_ version of the variable was found so return its value. 231 return default_value 232 233 return default 234 235 236def srequired_plug_in(req_plug_in_names, 237 plug_in_dir_paths=None): 238 r""" 239 Return an empty string if the required plug-ins are found in 240 plug_in_dir_paths. Otherwise, return an error string. 241 242 Example call: 243 error_message = srequired_plug_in(req_plug_in_names, plug_in_dir_paths) 244 245 Description of argument(s): 246 req_plug_in_names A list of plug_in names that the caller 247 requires (e.g. ['OS_Console']). 248 plug_in_dir_paths A string which is a colon-delimited list 249 of plug-ins specified by the user (e.g. 250 DB_Logging:FFDC:OS_Console:Perf). Path 251 values (e.g. "/home/robot/dir1") will be 252 stripped from this list to do the 253 analysis. Default value is the 254 AUTOBOOT_PLUG_IN_DIR_PATHS environment 255 variable. 256 """ 257 258 # Calculate default value for plug_in_dir_paths. 259 if plug_in_dir_paths is None: 260 plug_in_dir_paths = os.environ.get("AUTOBOOT_PLUG_IN_DIR_PATHS", "") 261 262 error_message = "" 263 264 # Convert plug_in_dir_paths to a list of base names. 265 plug_in_dir_paths = \ 266 filter(None, map(os.path.basename, plug_in_dir_paths.split(":"))) 267 268 # Check for each of the user's required plug-ins. 269 for plug_in_name in req_plug_in_names: 270 if plug_in_name not in plug_in_dir_paths: 271 error_message = "The \"" + get_plug_in_package_name() +\ 272 "\" plug-in cannot run unless the user also selects the \"" +\ 273 plug_in_name + "\" plug in:\n" +\ 274 gp.sprint_var(plug_in_dir_paths) 275 276 return error_message 277 278 279def required_plug_in(req_plug_in_names, 280 plug_in_dir_paths=None): 281 r""" 282 Return True if each of the plug-ins in req_plug_in_names can be found in 283 plug_in_dir_paths Otherwise, return False and print an error message to 284 stderr. 285 286 Example call: 287 if not required_plug_in(['OS_Console'], AUTOBOOT_PLUG_IN_DIR_PATHS): 288 return False 289 290 Description of argument(s): 291 (See Description of arguments for srequired_plug_in (above)). 292 """ 293 294 error_message = srequired_plug_in(req_plug_in_names, plug_in_dir_paths) 295 if not error_message == "": 296 gp.print_error_report(error_message) 297 return False 298 299 return True 300 301 302# Create print wrapper functions for all sprint functions defined above. 303# func_names contains a list of all print functions which should be created 304# from their sprint counterparts. 305func_names = ['print_plug_vars'] 306 307# stderr_func_names is a list of functions whose output should go to stderr 308# rather than stdout. 309stderr_func_names = [] 310 311replace_dict = dict(gp.replace_dict) 312replace_dict['mod_qualifier'] = 'gp.' 313func_defs = gp.create_print_wrapper_funcs(func_names, stderr_func_names, 314 replace_dict) 315gp.gp_debug_print(func_defs) 316exec(func_defs) 317