blob: dbbafe54c23f9f2b42fbd01dcdf0e7e476483546 [file] [log] [blame]
George Keishinge7e91712021-09-03 11:28:44 -05001#!/usr/bin/env python3
Michael Walshf4c62a22017-11-13 15:40:57 -06002
3r"""
4This module provides functions which are useful to plug-in call point programs.
5"""
6
Patrick Williams57318182022-12-08 06:18:26 -06007import collections
Michael Walshf4c62a22017-11-13 15:40:57 -06008import os
9import re
Patrick Williams57318182022-12-08 06:18:26 -060010import sys
Michael Walshf4c62a22017-11-13 15:40:57 -060011
Patrick Williams57318182022-12-08 06:18:26 -060012import func_args as fa
13import gen_cmd as gc
14import gen_misc as gm
Michael Walshf4c62a22017-11-13 15:40:57 -060015import gen_print as gp
Michael Walshe5599df2019-11-20 14:05:10 -060016import gen_valid as gv
Michael Walsha6b46ed2018-06-01 14:31:23 -050017
18PLUG_VAR_PREFIX = os.environ.get("PLUG_VAR_PREFIX", "AUTOBOOT")
Michael Walshf4c62a22017-11-13 15:40:57 -060019
20
21def get_plug_in_package_name(case=None):
Michael Walshf4c62a22017-11-13 15:40:57 -060022 r"""
23 Return the plug-in package name (e.g. "OS_Console", "DB_Logging").
24
25 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -050026 case Indicates whether the value returned should be converted to upper or
27 lower case. Valid values are "upper", "lower" or None.
Michael Walshf4c62a22017-11-13 15:40:57 -060028 """
29
30 plug_in_package_name = os.path.basename(gp.pgm_dir_path[:-1])
31 if case == "upper":
32 return plug_in_package_name.upper()
33 elif case == "lower":
34 return plug_in_package_name.lower()
35 else:
36 return plug_in_package_name
37
38
Patrick Williams57318182022-12-08 06:18:26 -060039def return_plug_vars(general=True, custom=True, plug_in_package_name=None):
Michael Walshf4c62a22017-11-13 15:40:57 -060040 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -050041 Return an OrderedDict which is sorted by key and which contains all of the plug-in environment variables.
Michael Walshf4c62a22017-11-13 15:40:57 -060042
43 Example excerpt of resulting dictionary:
44
45 plug_var_dict:
Michael Walsh2ce1dba2019-02-05 19:29:28 +000046 [AUTOBOOT_BASE_TOOL_DIR_PATH]: /tmp/
Michael Walshf4c62a22017-11-13 15:40:57 -060047 [AUTOBOOT_BB_LEVEL]: <blank>
48 [AUTOBOOT_BOOT_FAIL]: 0
49 ...
50
51 This function also does the following:
Michael Walsh0cb727d2019-10-16 17:16:45 -050052 - Set a default value for environment variable AUTOBOOT_OPENBMC_NICKNAME/AUTOIPL_FSP1_NICKNAME if it is
53 not already set.
Michael Walshf4c62a22017-11-13 15:40:57 -060054 - Register PASSWORD variables to prevent their values from being printed.
Michael Walsha6b46ed2018-06-01 14:31:23 -050055
Michael Walsh0cb727d2019-10-16 17:16:45 -050056 Note: The programmer may set a default for any given environment variable by declaring a global variable
57 of the same name and setting its value. For example, let's say the calling program has this global
58 declaration:
Michael Walsha6b46ed2018-06-01 14:31:23 -050059
60 PERF_EXERCISERS_TOTAL_TIMEOUT = '180'
61
Michael Walsh0cb727d2019-10-16 17:16:45 -050062 If environment variable PERF_EXERCISERS_TOTAL_TIMEOUT is blank or not set, this function will set it to
63 '180'.
64
65 Furthermore, if such a default variable declaration is not a string, this function will preserve that
66 non-string type in setting global variables (with the exception of os.environ values which must be
67 string). Example:
68
69 NVDIMM_ENCRYPT = 0
Michael Walshfd7443d2018-10-30 13:12:18 -050070
71 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -050072 general Return general plug-in parms (e.g. those beginning with "AUTOBOOT" or
73 "AUTOGUI").
74 custom Return custom plug-in parms (i.e. those beginning with the upper case
75 name of the plug-in package, for example "OBMC_SAMPLE_PARM1").
Michael Walshaeeb5272019-11-20 13:58:47 -060076 plug_in_package_name The name of the plug-in package for which custom parms are to be
77 returned. The default is the current plug in package name.
Michael Walshf4c62a22017-11-13 15:40:57 -060078 """
79
Michael Walshfd7443d2018-10-30 13:12:18 -050080 regex_list = []
81 if not (general or custom):
82 return collections.OrderedDict()
Patrick Williams57318182022-12-08 06:18:26 -060083 plug_in_package_name = gm.dft(
84 plug_in_package_name, get_plug_in_package_name()
85 )
Michael Walshfd7443d2018-10-30 13:12:18 -050086 if general:
87 regex_list = [PLUG_VAR_PREFIX, "AUTOGUI"]
88 if custom:
Michael Walshaeeb5272019-11-20 13:58:47 -060089 regex_list.append(plug_in_package_name.upper())
Michael Walshfd7443d2018-10-30 13:12:18 -050090
91 regex = "^(" + "|".join(regex_list) + ")_"
Michael Walshf4c62a22017-11-13 15:40:57 -060092
93 # Set a default for nickname.
94 if os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "") == "":
Patrick Williams57318182022-12-08 06:18:26 -060095 os.environ["AUTOBOOT_OPENBMC_NICKNAME"] = os.environ.get(
96 "AUTOBOOT_OPENBMC_HOST", ""
97 )
Michael Walshf4c62a22017-11-13 15:40:57 -060098
Michael Walsha6b46ed2018-06-01 14:31:23 -050099 if os.environ.get("AUTOIPL_FSP1_NICKNAME", "") == "":
Patrick Williams57318182022-12-08 06:18:26 -0600100 os.environ["AUTOIPL_FSP1_NICKNAME"] = os.environ.get(
101 "AUTOIPL_FSP1_NAME", ""
102 ).split(".")[0]
Michael Walsha6b46ed2018-06-01 14:31:23 -0500103
Michael Walsh0cb727d2019-10-16 17:16:45 -0500104 # For all variables specified in the parm_def file, we want them to default to "" rather than being unset.
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500105 # Process the parm_def file if it exists.
Patrick Williams57318182022-12-08 06:18:26 -0600106 parm_def_file_path = (
107 os.path.dirname(gp.pgm_dir_path.rstrip("/"))
108 + "/"
109 + plug_in_package_name
Michael Walshaeeb5272019-11-20 13:58:47 -0600110 + "/parm_def"
Patrick Williams57318182022-12-08 06:18:26 -0600111 )
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500112 if os.path.exists(parm_def_file_path):
113 parm_defs = gm.my_parm_file(parm_def_file_path)
114 else:
115 parm_defs = collections.OrderedDict()
116 # Example parm_defs:
117 # parm_defs:
118 # parm_defs[rest_fail]: boolean
119 # parm_defs[command]: string
120 # parm_defs[esel_stop_file_path]: string
121
Michael Walsh0cb727d2019-10-16 17:16:45 -0500122 # Create a list of plug-in environment variables by pre-pending <all caps plug-in package name>_<all
123 # caps var name>
Patrick Williams57318182022-12-08 06:18:26 -0600124 plug_in_parm_names = [
125 plug_in_package_name.upper() + "_" + x
126 for x in map(str.upper, parm_defs.keys())
127 ]
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500128 # Example plug_in_parm_names:
129 # plug_in_parm_names:
130 # plug_in_parm_names[0]: STOP_REST_FAIL
131 # plug_in_parm_names[1]: STOP_COMMAND
132 # plug_in_parm_names[2]: STOP_ESEL_STOP_FILE_PATH
133
Michael Walsh0cb727d2019-10-16 17:16:45 -0500134 # os.environ only accepts string values. However, if the user defines default values of other types
135 # (e.g. int), we wish to preserve the type.
136 non_string_defaults = {}
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500137 # Initialize unset plug-in vars.
138 for var_name in plug_in_parm_names:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500139 # If there is a global variable with the same name as the environment variable, use its value as a
140 # default.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500141 default_value = gm.get_mod_global(var_name, "")
Michael Walsh0cb727d2019-10-16 17:16:45 -0500142 if type(default_value) is not str:
143 non_string_defaults[var_name] = type(default_value)
144 os.environ[var_name] = os.environ.get(var_name, str(default_value))
Michael Walsha6b46ed2018-06-01 14:31:23 -0500145 if os.environ[var_name] == "":
Michael Walshc1df1502019-11-04 14:38:13 -0600146 os.environ[var_name] = str(default_value)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500147
Patrick Williams57318182022-12-08 06:18:26 -0600148 plug_var_dict = collections.OrderedDict(
149 sorted(
150 {
151 k: v for (k, v) in os.environ.items() if re.match(regex, k)
152 }.items()
153 )
154 )
Michael Walsh0cb727d2019-10-16 17:16:45 -0500155 # Restore the types of any variables where the caller had defined default values.
156 for key, value in non_string_defaults.items():
Patrick Williams57318182022-12-08 06:18:26 -0600157 cmd_buf = (
158 "plug_var_dict[key] = "
159 + str(value).split("'")[1]
160 + "(plug_var_dict[key]"
161 )
Michael Walsh0cb727d2019-10-16 17:16:45 -0500162 if value is int:
163 # Use int base argument of 0 to allow it to interpret hex strings.
164 cmd_buf += ", 0)"
165 else:
166 cmd_buf += ")"
Michael Walshc09b7cb2019-10-22 10:39:17 -0500167 exec(cmd_buf) in globals(), locals()
Michael Walsh0cb727d2019-10-16 17:16:45 -0500168 # Register password values to prevent printing them out. Any plug var whose name ends in PASSWORD will
169 # be registered.
Patrick Williams57318182022-12-08 06:18:26 -0600170 password_vals = {
171 k: v
172 for (k, v) in plug_var_dict.items()
173 if re.match(r".*_PASSWORD$", k)
174 }.values()
Michael Walshf4c62a22017-11-13 15:40:57 -0600175 map(gp.register_passwords, password_vals)
176
177 return plug_var_dict
178
179
Michael Walshfd7443d2018-10-30 13:12:18 -0500180def sprint_plug_vars(headers=1, **kwargs):
Michael Walshf4c62a22017-11-13 15:40:57 -0600181 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500182 Sprint the plug-in environment variables (i.e. those that begin with the global PLUG_VAR_PREFIX value or
183 those that begin with <plug-in package_name>_ in upper case letters.).
Michael Walshf4c62a22017-11-13 15:40:57 -0600184
185 Example excerpt of output:
Michael Walsh2ce1dba2019-02-05 19:29:28 +0000186 AUTOBOOT_BASE_TOOL_DIR_PATH=/tmp/
Michael Walshf4c62a22017-11-13 15:40:57 -0600187 AUTOBOOT_BB_LEVEL=
188 AUTOBOOT_BOOT_FAIL=0
189 AUTOBOOT_BOOT_FAIL_THRESHOLD=1000000
190
191 Description of argument(s):
192 headers Print a header and a footer.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500193 kwargs These are passed directly to return_plug_vars. See return_plug_vars doc
194 string for details.
Michael Walshf4c62a22017-11-13 15:40:57 -0600195 """
Michael Walshfd7443d2018-10-30 13:12:18 -0500196 plug_var_dict = return_plug_vars(**kwargs)
Michael Walshf4c62a22017-11-13 15:40:57 -0600197 buffer = ""
198 if headers:
199 buffer += "\n" + gp.sprint_dashes()
200 for key, value in plug_var_dict.items():
Michael Walshfd7443d2018-10-30 13:12:18 -0500201 buffer += gp.sprint_varx(key, value)
Michael Walshf4c62a22017-11-13 15:40:57 -0600202 if headers:
203 buffer += gp.sprint_dashes() + "\n"
204
205 return buffer
206
207
Michael Walshfd7443d2018-10-30 13:12:18 -0500208def print_plug_in_header():
209 r"""
210 Print plug-in header.
211
Michael Walsh0cb727d2019-10-16 17:16:45 -0500212 When debug is set, print all plug_prefix variables (e.g. AUTOBOOT_OPENBMC_HOST, etc.) and all plug-in
213 environment variables (e.g. OBMC_SAMPLE_PARM1) with surrounding dashed lines. When debug is not set,
214 print only the plug-in environment variables (e.g. OBMC_SAMPLE_PARM1) with no surrounding dashed lines.
Michael Walshfd7443d2018-10-30 13:12:18 -0500215
Michael Walsh0cb727d2019-10-16 17:16:45 -0500216 NOTE: plug-in environment variables means any variable defined in the <plug-in dir>/parm_def file plus
217 any environment variables whose names begin with the upper-case plug-in package name.
Michael Walshfd7443d2018-10-30 13:12:18 -0500218 """
219
220 dprint_plug_vars()
221 if not debug:
222 qprint_plug_vars(headers=0, general=False, custom=True)
223
224
Michael Walsh47f8a602019-11-20 14:02:11 -0600225def get_plug_vars(mod_name="__main__", **kwargs):
Michael Walshf4c62a22017-11-13 15:40:57 -0600226 r"""
227 Get all plug-in variables and put them in corresponding global variables.
228
Michael Walsh0cb727d2019-10-16 17:16:45 -0500229 This would include all environment variables beginning with either the global PLUG_VAR_PREFIX value or
230 with the upper case version of the plug-in package name + underscore (e.g. OP_SAMPLE_VAR1 for plug-in
231 OP_Sample).
Michael Walshf4c62a22017-11-13 15:40:57 -0600232
Michael Walsh0cb727d2019-10-16 17:16:45 -0500233 The global variables to be set will be both with and without the global PLUG_VAR_PREFIX value prefix.
234 For example, if the environment variable in question is AUTOBOOT_OPENBMC_HOST, this function will set
235 global variable AUTOBOOT_OPENBMC_HOST and global variable OPENBMC_HOST.
Michael Walsh8b79b052019-05-02 17:07:08 -0500236
237 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500238 mod_name The name of the module whose global plug-in variables should be retrieved.
Michael Walsh47f8a602019-11-20 14:02:11 -0600239 kwargs These are passed directly to return_plug_vars. See return_plug_vars's
240 prolog for details.
Michael Walshf4c62a22017-11-13 15:40:57 -0600241 """
242
Michael Walsh8b79b052019-05-02 17:07:08 -0500243 module = sys.modules[mod_name]
Michael Walsh47f8a602019-11-20 14:02:11 -0600244 plug_var_dict = return_plug_vars(**kwargs)
Michael Walshf4c62a22017-11-13 15:40:57 -0600245
Michael Walsha6b46ed2018-06-01 14:31:23 -0500246 # Get all PLUG_VAR_PREFIX environment variables and put them into globals.
Michael Walshf4c62a22017-11-13 15:40:57 -0600247 for key, value in plug_var_dict.items():
248 setattr(module, key, value)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500249 setattr(module, re.sub("^" + PLUG_VAR_PREFIX + "_", "", key), value)
Michael Walshf4c62a22017-11-13 15:40:57 -0600250
251
Patrick Williams57318182022-12-08 06:18:26 -0600252def get_plug_default(var_name, default=None):
Michael Walshf4c62a22017-11-13 15:40:57 -0600253 r"""
254 Derive and return a default value for the given parm variable.
255
Michael Walsha6b46ed2018-06-01 14:31:23 -0500256 Dependencies:
257 Global variable PLUG_VAR_PREFIX must be set.
258
Michael Walsh0cb727d2019-10-16 17:16:45 -0500259 This function will assign a default by checking the following environment variables in the order shown.
260 The first one that has a value will be used.
Michael Walshf4c62a22017-11-13 15:40:57 -0600261 - <upper case package_name>_<var_name>
Michael Walsha6b46ed2018-06-01 14:31:23 -0500262 - <PLUG_VAR_PREFIX>_OVERRIDE_<var_name>
263 - <PLUG_VAR_PREFIX>_<var_name>
Michael Walshf4c62a22017-11-13 15:40:57 -0600264
Michael Walsh0cb727d2019-10-16 17:16:45 -0500265 If none of these are found, this function will return the value passed by the caller in the "default"
266 parm.
Michael Walshf4c62a22017-11-13 15:40:57 -0600267
268 Example:
269
Michael Walsh0cb727d2019-10-16 17:16:45 -0500270 Let's say your plug-in is named "OS_Console" and you call this function as follows:
Michael Walshf4c62a22017-11-13 15:40:57 -0600271
272 get_plug_default("quiet", 0)
273
Michael Walsh0cb727d2019-10-16 17:16:45 -0500274 The first of these environment variables that is found to be set will be used to provide the default
275 value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600276 - OS_CONSOLE_QUIET
277 - AUTOBOOT_OVERRIDE_QUIET
278 - AUTOBOOT_QUIET
279
Michael Walsh0cb727d2019-10-16 17:16:45 -0500280 If none of those has a value, 0 (as specified by the caller in this example) is returned.
Michael Walshf4c62a22017-11-13 15:40:57 -0600281
Michael Walsh0cb727d2019-10-16 17:16:45 -0500282 Let's say the master driver program is named obmc_boot. obmc_boot program is responsible for calling
283 plug-ins. Let's further suppose that the user wishes to run the master program with --debug=0 but wishes
284 to have all plug-ins run with --debug=1. This could be accomplished with the following call:
285 export AUTOBOOT_OVERRIDE_DEBUG=1 ; obmc_boot --debug=0 --plug_in_dir_paths=<list of plug ins>
286
287 As another example, let's suppose that the user wishes to have just the OS_Console plug-in run with debug
288 and everything else to default to debug=0. This could be accomplished as follows:
289 export OS_CONSOLE_DEBUG=1 ; obmc_boot --debug=0 --plug_in_dir_paths=<list of plug ins>
290
291 And as one more example, let's say the user wishes to have obmc_boot and OS_Console run without debug but
292 have all other plug-ins run with debug:
293 export AUTOBOOT_OVERRIDE_DEBUG=1 ; export OS_CONSOLE_DEBUG=0 ; obmc_boot --debug=0
Michael Walshf4c62a22017-11-13 15:40:57 -0600294 --plug_in_dir_paths=<list of plug ins>
295
Michael Walshf4c62a22017-11-13 15:40:57 -0600296 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500297 var_name The name of the variable for which a default value is to be calculated.
298 default The default value if one cannot be determined.
Michael Walshf4c62a22017-11-13 15:40:57 -0600299 """
300
301 var_name = var_name.upper()
302 plug_in_package_name = get_plug_in_package_name(case="upper")
303
304 package_var_name = plug_in_package_name + "_" + var_name
305 default_value = os.environ.get(package_var_name, None)
306 if default_value is not None:
307 # A package-name version of the variable was found so return its value.
Patrick Williams57318182022-12-08 06:18:26 -0600308 return default_value
Michael Walshf4c62a22017-11-13 15:40:57 -0600309
Michael Walsha6b46ed2018-06-01 14:31:23 -0500310 plug_var_name = PLUG_VAR_PREFIX + "_OVERRIDE_" + var_name
311 default_value = os.environ.get(plug_var_name, None)
Michael Walshf4c62a22017-11-13 15:40:57 -0600312 if default_value is not None:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500313 # A PLUG_VAR_PREFIX version of the variable was found so return its value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600314 return default_value
315
Michael Walsha6b46ed2018-06-01 14:31:23 -0500316 plug_var_name = PLUG_VAR_PREFIX + "_" + var_name
317 default_value = os.environ.get(plug_var_name, None)
Michael Walshf4c62a22017-11-13 15:40:57 -0600318 if default_value is not None:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500319 # A PLUG_VAR_PREFIX version of the variable was found so return its value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600320 return default_value
321
322 return default
323
324
Patrick Williams57318182022-12-08 06:18:26 -0600325def required_plug_in(required_plug_in_names, plug_in_dir_paths=None):
Michael Walshf4c62a22017-11-13 15:40:57 -0600326 r"""
Michael Walshe5599df2019-11-20 14:05:10 -0600327 Determine whether the required_plug_in_names are in plug_in_dir_paths, construct an error_message and
328 call gv.process_error_message(error_message).
329
330 In addition, for each plug-in in required_plug_in_names, set the global plug-in variables. This is
331 useful for callers who then want to validate certain values from other plug-ins.
Michael Walshf4c62a22017-11-13 15:40:57 -0600332
333 Example call:
Michael Walshe5599df2019-11-20 14:05:10 -0600334 required_plug_in(required_plug_in_names)
Michael Walshf4c62a22017-11-13 15:40:57 -0600335
336 Description of argument(s):
Michael Walshe5599df2019-11-20 14:05:10 -0600337 required_plug_in_names A list of plug_in names that the caller requires (e.g. ['OS_Console']).
Michael Walsh0cb727d2019-10-16 17:16:45 -0500338 plug_in_dir_paths A string which is a colon-delimited list of plug-ins specified by the
339 user (e.g. DB_Logging:FFDC:OS_Console:Perf). Path values (e.g.
340 "/home/robot/dir1") will be stripped from this list to do the analysis.
Michael Walshe5599df2019-11-20 14:05:10 -0600341 Default value is the AUTOGUI_PLUG_IN_DIR_PATHS or
342 <PLUG_VAR_PREFIX>_PLUG_IN_DIR_PATHS environment variable.
Michael Walshf4c62a22017-11-13 15:40:57 -0600343 """
344
345 # Calculate default value for plug_in_dir_paths.
Patrick Williams57318182022-12-08 06:18:26 -0600346 plug_in_dir_paths = gm.dft(
347 plug_in_dir_paths,
348 os.environ.get(
349 "AUTOGUI_PLUG_IN_DIR_PATHS",
350 os.environ.get(PLUG_VAR_PREFIX + "_PLUG_IN_DIR_PATHS", ""),
351 ),
352 )
Michael Walshf4c62a22017-11-13 15:40:57 -0600353
354 # Convert plug_in_dir_paths to a list of base names.
Patrick Williams57318182022-12-08 06:18:26 -0600355 plug_in_dir_paths = list(
356 filter(None, map(os.path.basename, plug_in_dir_paths.split(":")))
357 )
Michael Walshf4c62a22017-11-13 15:40:57 -0600358
Patrick Williams57318182022-12-08 06:18:26 -0600359 error_message = gv.valid_list(
360 plug_in_dir_paths, required_values=required_plug_in_names
361 )
Michael Walshe5599df2019-11-20 14:05:10 -0600362 if error_message:
363 return gv.process_error_message(error_message)
Michael Walshf4c62a22017-11-13 15:40:57 -0600364
Michael Walshe5599df2019-11-20 14:05:10 -0600365 for plug_in_package_name in required_plug_in_names:
366 get_plug_vars(general=False, plug_in_package_name=plug_in_package_name)
Michael Walshf4c62a22017-11-13 15:40:57 -0600367
368
Michael Walsh96ffeb72018-08-23 11:37:22 -0500369def compose_plug_in_save_dir_path(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500370 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500371 Create and return a directory path name that is suitable for saving plug-in data.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500372
Michael Walsh0cb727d2019-10-16 17:16:45 -0500373 The name will be comprised of things such as plug_in package name, pid, etc. in order to guarantee that
374 it is unique for a given test run.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500375
376 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500377 plug_in_package_name The plug-in package name. This defaults to the name of the caller's
378 plug-in package. However, the caller can specify another value in order
379 to retrieve data saved by another plug-in package.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500380 """
381
Patrick Williams57318182022-12-08 06:18:26 -0600382 plug_in_package_name = gm.dft(
383 plug_in_package_name, get_plug_in_package_name()
384 )
Michael Walsh96ffeb72018-08-23 11:37:22 -0500385
Patrick Williams57318182022-12-08 06:18:26 -0600386 BASE_TOOL_DIR_PATH = gm.add_trailing_slash(
387 os.environ.get(PLUG_VAR_PREFIX + "_BASE_TOOL_DIR_PATH", "/tmp/")
388 )
Michael Walsha6b46ed2018-06-01 14:31:23 -0500389 NICKNAME = os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "")
390 if NICKNAME == "":
391 NICKNAME = os.environ["AUTOIPL_FSP1_NICKNAME"]
392 MASTER_PID = os.environ[PLUG_VAR_PREFIX + "_MASTER_PID"]
Patrick Williams57318182022-12-08 06:18:26 -0600393 gp.dprint_vars(
394 BASE_TOOL_DIR_PATH, NICKNAME, plug_in_package_name, MASTER_PID
395 )
396 return (
397 BASE_TOOL_DIR_PATH
398 + gm.username()
399 + "/"
400 + NICKNAME
401 + "/"
402 + plug_in_package_name
403 + "/"
404 + str(MASTER_PID)
405 + "/"
406 )
Michael Walsha6b46ed2018-06-01 14:31:23 -0500407
408
Michael Walsh96ffeb72018-08-23 11:37:22 -0500409def create_plug_in_save_dir(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500410 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500411 Create a directory suitable for saving plug-in processing data and return its path name.
Michael Walsh024a2f32019-04-18 10:55:34 -0500412
413 See compose_plug_in_save_dir_path for details.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500414
415 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500416 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500417 """
418
Michael Walsh96ffeb72018-08-23 11:37:22 -0500419 plug_in_save_dir_path = compose_plug_in_save_dir_path(plug_in_package_name)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500420 if os.path.isdir(plug_in_save_dir_path):
421 return plug_in_save_dir_path
422 gc.shell_cmd("mkdir -p " + plug_in_save_dir_path)
423 return plug_in_save_dir_path
424
425
Michael Walsh96ffeb72018-08-23 11:37:22 -0500426def delete_plug_in_save_dir(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500427 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500428 Delete the plug_in save directory. See compose_plug_in_save_dir_path for details.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500429
430 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500431 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500432 """
433
Patrick Williams57318182022-12-08 06:18:26 -0600434 gc.shell_cmd(
435 "rm -rf " + compose_plug_in_save_dir_path(plug_in_package_name)
436 )
Michael Walsha6b46ed2018-06-01 14:31:23 -0500437
438
Michael Walshaa736b52019-11-20 14:14:31 -0600439def save_plug_in_value(var_value=None, plug_in_package_name=None, **kwargs):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500440 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500441 Save a value in a plug-in save file. The value may be retrieved later via a call to the
442 restore_plug_in_value function.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500443
Michael Walshaa736b52019-11-20 14:14:31 -0600444 This function will figure out the variable name corresponding to the value passed and use that name in
445 creating the plug-in save file.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500446
Michael Walshaa736b52019-11-20 14:14:31 -0600447 The caller may pass the value as a simple variable or as a keyword=value (see examples below).
448
449 Example 1:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500450
451 my_var1 = 5
452 save_plug_in_value(my_var1)
453
Michael Walsh0cb727d2019-10-16 17:16:45 -0500454 In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500455
Michael Walshaa736b52019-11-20 14:14:31 -0600456 Example 2:
457
458 save_plug_in_value(my_var1=5)
459
460 In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory.
461
Michael Walsha6b46ed2018-06-01 14:31:23 -0500462 Description of argument(s):
Michael Walshaa736b52019-11-20 14:14:31 -0600463 var_value The value to be saved.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500464 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walshaa736b52019-11-20 14:14:31 -0600465 kwargs The first entry may contain a var_name/var_value. Other entries are
466 ignored.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500467 """
468
Michael Walshaa736b52019-11-20 14:14:31 -0600469 if var_value is None:
470 var_name = next(iter(kwargs))
471 var_value = kwargs[var_name]
472 else:
473 # Get the name of the variable used as argument one to this function.
474 var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
Michael Walsh96ffeb72018-08-23 11:37:22 -0500475 plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500476 save_file_path = plug_in_save_dir_path + var_name
Patrick Williams57318182022-12-08 06:18:26 -0600477 gp.qprint_timen('Saving "' + var_name + '" value.')
Michael Walshaa736b52019-11-20 14:14:31 -0600478 gp.qprint_varx(var_name, var_value)
479 gc.shell_cmd("echo '" + str(var_value) + "' > " + save_file_path)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500480
481
Michael Walshaa736b52019-11-20 14:14:31 -0600482def restore_plug_in_value(*args, **kwargs):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500483 r"""
484 Return a value from a plug-in save file.
485
Michael Walshaa736b52019-11-20 14:14:31 -0600486 The args/kwargs are interpreted differently depending on how this function is called.
487
488 Mode 1 - The output of this function is assigned to a variable:
489
490 Example:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500491
492 my_var1 = restore_plug_in_value(2)
493
Michael Walshaa736b52019-11-20 14:14:31 -0600494 In this mode, the lvalue ("my_var1" in this example) will serve as the name of the value to be restored.
495
496 Mode 2 - The output of this function is NOT assigned to a variable:
497
498 Example:
499
500 if restore_plug_in_value('my_var1', 2):
501 do_something()
502
503 In this mode, the caller must explicitly provide the name of the value being restored.
504
505 The args/kwargs are interpreted as follows:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500506
507 Description of argument(s):
Michael Walshaa736b52019-11-20 14:14:31 -0600508 var_name The name of the value to be restored. Only relevant in mode 1 (see
509 example above).
Michael Walsh0cb727d2019-10-16 17:16:45 -0500510 default The default value to be returned if there is no plug-in save file for the
511 value in question.
512 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500513 """
Michael Walshaa736b52019-11-20 14:14:31 -0600514 # Process args.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500515 lvalue = gp.get_arg_name(0, -1, stack_frame_ix=2)
Michael Walshaa736b52019-11-20 14:14:31 -0600516 if lvalue:
517 var_name = lvalue
518 else:
519 var_name, args, kwargs = fa.pop_arg("", *args, **kwargs)
520 default, args, kwargs = fa.pop_arg("", *args, **kwargs)
521 plug_in_package_name, args, kwargs = fa.pop_arg(None, *args, **kwargs)
522 if args or kwargs:
Patrick Williams57318182022-12-08 06:18:26 -0600523 error_message = (
524 "Programmer error - Too many arguments passed for this function."
525 )
Michael Walshaa736b52019-11-20 14:14:31 -0600526 raise ValueError(error_message)
Michael Walsh96ffeb72018-08-23 11:37:22 -0500527 plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name)
Michael Walshaa736b52019-11-20 14:14:31 -0600528 save_file_path = plug_in_save_dir_path + var_name
Michael Walsha6b46ed2018-06-01 14:31:23 -0500529 if os.path.isfile(save_file_path):
Patrick Williams57318182022-12-08 06:18:26 -0600530 gp.qprint_timen(
531 "Restoring " + var_name + " value from " + save_file_path + "."
532 )
533 var_value = gm.file_to_list(
534 save_file_path, newlines=0, comments=0, trim=1
535 )[0]
Michael Walsh25f0f162018-09-10 13:57:11 -0500536 if type(default) is bool:
537 # Convert from string to bool.
Patrick Williams57318182022-12-08 06:18:26 -0600538 var_value = var_value == "True"
Michael Walsh25f0f162018-09-10 13:57:11 -0500539 if type(default) is int:
540 # Convert from string to int.
Michael Walshaa736b52019-11-20 14:14:31 -0600541 var_value = int(var_value)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500542 else:
Michael Walshaa736b52019-11-20 14:14:31 -0600543 var_value = default
Patrick Williams57318182022-12-08 06:18:26 -0600544 gp.qprint_timen(
545 "Save file "
546 + save_file_path
547 + " does not exist so returning default value."
548 )
Michael Walshaa736b52019-11-20 14:14:31 -0600549
550 gp.qprint_varx(var_name, var_value)
551 return var_value
Michael Walsha6b46ed2018-06-01 14:31:23 -0500552
553
Michael Walsh99beb652019-02-25 10:45:23 -0600554def exit_not_master():
555 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500556 Exit the program with return code zero if this program was NOT called by the master program.
Michael Walsh99beb652019-02-25 10:45:23 -0600557
558 There are cases where plug-ins are called by a multi-layered stack:
559
560 master_wrapper
561 obmc_boot_test.py
562 Example_plug_in/cp_setup
563
Michael Walsh0cb727d2019-10-16 17:16:45 -0500564 In a scenario like this, Example_plug_in/cp_setup may be called once directly by master_wrapper (the
565 master) and and then called again directly by obmc_boot_test.py (the child). Some plug-in programs may
566 wish to avoid doing any processing on the second such call. This function will achieve that purpose.
Michael Walsh99beb652019-02-25 10:45:23 -0600567
568 This function will print a standard message to stdout prior to exiting.
569 """
570
571 AUTOBOOT_MASTER_PID = gm.get_mod_global("AUTOBOOT_MASTER_PID")
572 AUTOBOOT_PROGRAM_PID = gm.get_mod_global("AUTOBOOT_PROGRAM_PID")
573
574 if AUTOBOOT_MASTER_PID != AUTOBOOT_PROGRAM_PID:
Patrick Williams57318182022-12-08 06:18:26 -0600575 message = (
576 get_plug_in_package_name()
577 + "/"
578 + gp.pgm_name
579 + " is not"
580 + " being called by the master program in the stack so no action"
Michael Walsh99beb652019-02-25 10:45:23 -0600581 + " will be taken."
Patrick Williams57318182022-12-08 06:18:26 -0600582 )
Michael Walsh99beb652019-02-25 10:45:23 -0600583 gp.qprint_timen(message)
584 gp.qprint_vars(AUTOBOOT_MASTER_PID, AUTOBOOT_PROGRAM_PID)
585 exit(0)
586
587
Michael Walsh925294d2020-06-23 17:42:57 -0500588def add_tarball_tools_dir_to_path(quiet=0):
589 r"""
590 Find the directory containing the tarball tools and pre-pend it to PATH.
591
592 The calling program is responsible for making sure that the tarball has been unpacked.
593 """
Patrick Williams57318182022-12-08 06:18:26 -0600594 AUTOBOOT_BASE_TOOL_DIR_PATH = gm.get_mod_global(
595 "AUTOBOOT_BASE_TOOL_DIR_PATH"
596 )
Michael Walsh925294d2020-06-23 17:42:57 -0500597 AUTOBOOT_OPENBMC_NICKNAME = gm.get_mod_global("AUTOBOOT_OPENBMC_NICKNAME")
598
Patrick Williams57318182022-12-08 06:18:26 -0600599 tool_dir_path = (
600 AUTOBOOT_BASE_TOOL_DIR_PATH
601 + os.environ.get("USER")
602 + os.sep
603 + AUTOBOOT_OPENBMC_NICKNAME
604 + os.sep
605 )
606 tarball_tools_dir_path = tool_dir_path + "tarball/x86/bin"
607 os.environ["PATH"] = gm.add_path(
608 tarball_tools_dir_path, os.environ.get("PATH", "")
609 )
Michael Walsh925294d2020-06-23 17:42:57 -0500610
611
Michael Walsh0cb727d2019-10-16 17:16:45 -0500612def stop_test_rc():
613 r"""
614 Return the constant stop test return code value.
615
616 When a plug-in call point program returns this value, it indicates that master program should stop
617 running.
618 """
619
620 return 0x00000002
621
622
Michael Walshf09e8af2020-05-05 13:54:15 -0500623def dump_ffdc_rc():
624 r"""
625 Return the constant dump FFDC return code value.
626
627 When a plug-in call point program returns this value, it indicates that FFDC data should be collected.
628 """
629
630 return 0x00000002
631
632
Michael Walshf4c62a22017-11-13 15:40:57 -0600633# Create print wrapper functions for all sprint functions defined above.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500634# func_names contains a list of all print functions which should be created from their sprint counterparts.
Patrick Williams57318182022-12-08 06:18:26 -0600635func_names = ["print_plug_vars"]
Michael Walshf4c62a22017-11-13 15:40:57 -0600636
Michael Walsh0cb727d2019-10-16 17:16:45 -0500637# stderr_func_names is a list of functions whose output should go to stderr rather than stdout.
Michael Walshf4c62a22017-11-13 15:40:57 -0600638stderr_func_names = []
639
640replace_dict = dict(gp.replace_dict)
Patrick Williams57318182022-12-08 06:18:26 -0600641replace_dict["mod_qualifier"] = "gp."
642func_defs = gp.create_print_wrapper_funcs(
643 func_names, stderr_func_names, replace_dict
644)
Michael Walshf4c62a22017-11-13 15:40:57 -0600645gp.gp_debug_print(func_defs)
646exec(func_defs)