blob: 825801fd9c90166a0afd9305c83ff2f5ec3d7b1b [file] [log] [blame]
Michael Walshf4c62a22017-11-13 15:40:57 -06001#!/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
Michael Walshe5599df2019-11-20 14:05:10 -060013import gen_valid as gv
Michael Walsh3ba8ecd2018-04-24 11:33:25 -050014import gen_misc as gm
Michael Walsha6b46ed2018-06-01 14:31:23 -050015import gen_cmd as gc
Michael Walshaa736b52019-11-20 14:14:31 -060016import func_args as fa
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
Michael Walshfd7443d2018-10-30 13:12:18 -050039def return_plug_vars(general=True,
Michael Walshaeeb5272019-11-20 13:58:47 -060040 custom=True,
41 plug_in_package_name=None):
Michael Walshf4c62a22017-11-13 15:40:57 -060042 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -050043 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 -060044
45 Example excerpt of resulting dictionary:
46
47 plug_var_dict:
Michael Walsh2ce1dba2019-02-05 19:29:28 +000048 [AUTOBOOT_BASE_TOOL_DIR_PATH]: /tmp/
Michael Walshf4c62a22017-11-13 15:40:57 -060049 [AUTOBOOT_BB_LEVEL]: <blank>
50 [AUTOBOOT_BOOT_FAIL]: 0
51 ...
52
53 This function also does the following:
Michael Walsh0cb727d2019-10-16 17:16:45 -050054 - Set a default value for environment variable AUTOBOOT_OPENBMC_NICKNAME/AUTOIPL_FSP1_NICKNAME if it is
55 not already set.
Michael Walshf4c62a22017-11-13 15:40:57 -060056 - Register PASSWORD variables to prevent their values from being printed.
Michael Walsha6b46ed2018-06-01 14:31:23 -050057
Michael Walsh0cb727d2019-10-16 17:16:45 -050058 Note: The programmer may set a default for any given environment variable by declaring a global variable
59 of the same name and setting its value. For example, let's say the calling program has this global
60 declaration:
Michael Walsha6b46ed2018-06-01 14:31:23 -050061
62 PERF_EXERCISERS_TOTAL_TIMEOUT = '180'
63
Michael Walsh0cb727d2019-10-16 17:16:45 -050064 If environment variable PERF_EXERCISERS_TOTAL_TIMEOUT is blank or not set, this function will set it to
65 '180'.
66
67 Furthermore, if such a default variable declaration is not a string, this function will preserve that
68 non-string type in setting global variables (with the exception of os.environ values which must be
69 string). Example:
70
71 NVDIMM_ENCRYPT = 0
Michael Walshfd7443d2018-10-30 13:12:18 -050072
73 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -050074 general Return general plug-in parms (e.g. those beginning with "AUTOBOOT" or
75 "AUTOGUI").
76 custom Return custom plug-in parms (i.e. those beginning with the upper case
77 name of the plug-in package, for example "OBMC_SAMPLE_PARM1").
Michael Walshaeeb5272019-11-20 13:58:47 -060078 plug_in_package_name The name of the plug-in package for which custom parms are to be
79 returned. The default is the current plug in package name.
Michael Walshf4c62a22017-11-13 15:40:57 -060080 """
81
Michael Walshfd7443d2018-10-30 13:12:18 -050082 regex_list = []
83 if not (general or custom):
84 return collections.OrderedDict()
Michael Walshaeeb5272019-11-20 13:58:47 -060085 plug_in_package_name = gm.dft(plug_in_package_name, get_plug_in_package_name())
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", "") == "":
95 os.environ['AUTOBOOT_OPENBMC_NICKNAME'] = \
96 os.environ.get("AUTOBOOT_OPENBMC_HOST", "")
97
Michael Walsha6b46ed2018-06-01 14:31:23 -050098 if os.environ.get("AUTOIPL_FSP1_NICKNAME", "") == "":
99 os.environ['AUTOIPL_FSP1_NICKNAME'] = \
100 os.environ.get("AUTOIPL_FSP1_NAME", "").split(".")[0]
101
Michael Walsh0cb727d2019-10-16 17:16:45 -0500102 # 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 -0500103 # Process the parm_def file if it exists.
Michael Walshaeeb5272019-11-20 13:58:47 -0600104 parm_def_file_path = os.path.dirname(gp.pgm_dir_path.rstrip("/")) + "/" + plug_in_package_name \
105 + "/parm_def"
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500106 if os.path.exists(parm_def_file_path):
107 parm_defs = gm.my_parm_file(parm_def_file_path)
108 else:
109 parm_defs = collections.OrderedDict()
110 # Example parm_defs:
111 # parm_defs:
112 # parm_defs[rest_fail]: boolean
113 # parm_defs[command]: string
114 # parm_defs[esel_stop_file_path]: string
115
Michael Walsh0cb727d2019-10-16 17:16:45 -0500116 # Create a list of plug-in environment variables by pre-pending <all caps plug-in package name>_<all
117 # caps var name>
Michael Walshaeeb5272019-11-20 13:58:47 -0600118 plug_in_parm_names = [plug_in_package_name.upper() + "_" + x for x in
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500119 map(str.upper, parm_defs.keys())]
120 # Example plug_in_parm_names:
121 # plug_in_parm_names:
122 # plug_in_parm_names[0]: STOP_REST_FAIL
123 # plug_in_parm_names[1]: STOP_COMMAND
124 # plug_in_parm_names[2]: STOP_ESEL_STOP_FILE_PATH
125
Michael Walsh0cb727d2019-10-16 17:16:45 -0500126 # os.environ only accepts string values. However, if the user defines default values of other types
127 # (e.g. int), we wish to preserve the type.
128 non_string_defaults = {}
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500129 # Initialize unset plug-in vars.
130 for var_name in plug_in_parm_names:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500131 # If there is a global variable with the same name as the environment variable, use its value as a
132 # default.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500133 default_value = gm.get_mod_global(var_name, "")
Michael Walsh0cb727d2019-10-16 17:16:45 -0500134 if type(default_value) is not str:
135 non_string_defaults[var_name] = type(default_value)
136 os.environ[var_name] = os.environ.get(var_name, str(default_value))
Michael Walsha6b46ed2018-06-01 14:31:23 -0500137 if os.environ[var_name] == "":
Michael Walshc1df1502019-11-04 14:38:13 -0600138 os.environ[var_name] = str(default_value)
Michael Walsh3ba8ecd2018-04-24 11:33:25 -0500139
Michael Walshf4c62a22017-11-13 15:40:57 -0600140 plug_var_dict = \
141 collections.OrderedDict(sorted({k: v for (k, v) in
Gunnar Mills096cd562018-03-26 10:19:12 -0500142 os.environ.items()
143 if re.match(regex, k)}.items()))
Michael Walsh0cb727d2019-10-16 17:16:45 -0500144 # Restore the types of any variables where the caller had defined default values.
145 for key, value in non_string_defaults.items():
146 cmd_buf = "plug_var_dict[key] = " + str(value).split("'")[1] + "(plug_var_dict[key]"
147 if value is int:
148 # Use int base argument of 0 to allow it to interpret hex strings.
149 cmd_buf += ", 0)"
150 else:
151 cmd_buf += ")"
Michael Walshc09b7cb2019-10-22 10:39:17 -0500152 exec(cmd_buf) in globals(), locals()
Michael Walsh0cb727d2019-10-16 17:16:45 -0500153 # Register password values to prevent printing them out. Any plug var whose name ends in PASSWORD will
154 # be registered.
Michael Walshf4c62a22017-11-13 15:40:57 -0600155 password_vals = {k: v for (k, v) in plug_var_dict.items()
156 if re.match(r".*_PASSWORD$", k)}.values()
157 map(gp.register_passwords, password_vals)
158
159 return plug_var_dict
160
161
Michael Walshfd7443d2018-10-30 13:12:18 -0500162def sprint_plug_vars(headers=1, **kwargs):
Michael Walshf4c62a22017-11-13 15:40:57 -0600163 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500164 Sprint the plug-in environment variables (i.e. those that begin with the global PLUG_VAR_PREFIX value or
165 those that begin with <plug-in package_name>_ in upper case letters.).
Michael Walshf4c62a22017-11-13 15:40:57 -0600166
167 Example excerpt of output:
Michael Walsh2ce1dba2019-02-05 19:29:28 +0000168 AUTOBOOT_BASE_TOOL_DIR_PATH=/tmp/
Michael Walshf4c62a22017-11-13 15:40:57 -0600169 AUTOBOOT_BB_LEVEL=
170 AUTOBOOT_BOOT_FAIL=0
171 AUTOBOOT_BOOT_FAIL_THRESHOLD=1000000
172
173 Description of argument(s):
174 headers Print a header and a footer.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500175 kwargs These are passed directly to return_plug_vars. See return_plug_vars doc
176 string for details.
Michael Walshf4c62a22017-11-13 15:40:57 -0600177 """
Michael Walshfd7443d2018-10-30 13:12:18 -0500178 plug_var_dict = return_plug_vars(**kwargs)
Michael Walshf4c62a22017-11-13 15:40:57 -0600179 buffer = ""
180 if headers:
181 buffer += "\n" + gp.sprint_dashes()
182 for key, value in plug_var_dict.items():
Michael Walshfd7443d2018-10-30 13:12:18 -0500183 buffer += gp.sprint_varx(key, value)
Michael Walshf4c62a22017-11-13 15:40:57 -0600184 if headers:
185 buffer += gp.sprint_dashes() + "\n"
186
187 return buffer
188
189
Michael Walshfd7443d2018-10-30 13:12:18 -0500190def print_plug_in_header():
191 r"""
192 Print plug-in header.
193
Michael Walsh0cb727d2019-10-16 17:16:45 -0500194 When debug is set, print all plug_prefix variables (e.g. AUTOBOOT_OPENBMC_HOST, etc.) and all plug-in
195 environment variables (e.g. OBMC_SAMPLE_PARM1) with surrounding dashed lines. When debug is not set,
196 print only the plug-in environment variables (e.g. OBMC_SAMPLE_PARM1) with no surrounding dashed lines.
Michael Walshfd7443d2018-10-30 13:12:18 -0500197
Michael Walsh0cb727d2019-10-16 17:16:45 -0500198 NOTE: plug-in environment variables means any variable defined in the <plug-in dir>/parm_def file plus
199 any environment variables whose names begin with the upper-case plug-in package name.
Michael Walshfd7443d2018-10-30 13:12:18 -0500200 """
201
202 dprint_plug_vars()
203 if not debug:
204 qprint_plug_vars(headers=0, general=False, custom=True)
205
206
Michael Walsh47f8a602019-11-20 14:02:11 -0600207def get_plug_vars(mod_name="__main__", **kwargs):
Michael Walshf4c62a22017-11-13 15:40:57 -0600208 r"""
209 Get all plug-in variables and put them in corresponding global variables.
210
Michael Walsh0cb727d2019-10-16 17:16:45 -0500211 This would include all environment variables beginning with either the global PLUG_VAR_PREFIX value or
212 with the upper case version of the plug-in package name + underscore (e.g. OP_SAMPLE_VAR1 for plug-in
213 OP_Sample).
Michael Walshf4c62a22017-11-13 15:40:57 -0600214
Michael Walsh0cb727d2019-10-16 17:16:45 -0500215 The global variables to be set will be both with and without the global PLUG_VAR_PREFIX value prefix.
216 For example, if the environment variable in question is AUTOBOOT_OPENBMC_HOST, this function will set
217 global variable AUTOBOOT_OPENBMC_HOST and global variable OPENBMC_HOST.
Michael Walsh8b79b052019-05-02 17:07:08 -0500218
219 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500220 mod_name The name of the module whose global plug-in variables should be retrieved.
Michael Walsh47f8a602019-11-20 14:02:11 -0600221 kwargs These are passed directly to return_plug_vars. See return_plug_vars's
222 prolog for details.
Michael Walshf4c62a22017-11-13 15:40:57 -0600223 """
224
Michael Walsh8b79b052019-05-02 17:07:08 -0500225 module = sys.modules[mod_name]
Michael Walsh47f8a602019-11-20 14:02:11 -0600226 plug_var_dict = return_plug_vars(**kwargs)
Michael Walshf4c62a22017-11-13 15:40:57 -0600227
Michael Walsha6b46ed2018-06-01 14:31:23 -0500228 # Get all PLUG_VAR_PREFIX environment variables and put them into globals.
Michael Walshf4c62a22017-11-13 15:40:57 -0600229 for key, value in plug_var_dict.items():
230 setattr(module, key, value)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500231 setattr(module, re.sub("^" + PLUG_VAR_PREFIX + "_", "", key), value)
Michael Walshf4c62a22017-11-13 15:40:57 -0600232
233
234def get_plug_default(var_name,
235 default=None):
Michael Walshf4c62a22017-11-13 15:40:57 -0600236 r"""
237 Derive and return a default value for the given parm variable.
238
Michael Walsha6b46ed2018-06-01 14:31:23 -0500239 Dependencies:
240 Global variable PLUG_VAR_PREFIX must be set.
241
Michael Walsh0cb727d2019-10-16 17:16:45 -0500242 This function will assign a default by checking the following environment variables in the order shown.
243 The first one that has a value will be used.
Michael Walshf4c62a22017-11-13 15:40:57 -0600244 - <upper case package_name>_<var_name>
Michael Walsha6b46ed2018-06-01 14:31:23 -0500245 - <PLUG_VAR_PREFIX>_OVERRIDE_<var_name>
246 - <PLUG_VAR_PREFIX>_<var_name>
Michael Walshf4c62a22017-11-13 15:40:57 -0600247
Michael Walsh0cb727d2019-10-16 17:16:45 -0500248 If none of these are found, this function will return the value passed by the caller in the "default"
249 parm.
Michael Walshf4c62a22017-11-13 15:40:57 -0600250
251 Example:
252
Michael Walsh0cb727d2019-10-16 17:16:45 -0500253 Let's say your plug-in is named "OS_Console" and you call this function as follows:
Michael Walshf4c62a22017-11-13 15:40:57 -0600254
255 get_plug_default("quiet", 0)
256
Michael Walsh0cb727d2019-10-16 17:16:45 -0500257 The first of these environment variables that is found to be set will be used to provide the default
258 value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600259 - OS_CONSOLE_QUIET
260 - AUTOBOOT_OVERRIDE_QUIET
261 - AUTOBOOT_QUIET
262
Michael Walsh0cb727d2019-10-16 17:16:45 -0500263 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 -0600264
Michael Walsh0cb727d2019-10-16 17:16:45 -0500265 Let's say the master driver program is named obmc_boot. obmc_boot program is responsible for calling
266 plug-ins. Let's further suppose that the user wishes to run the master program with --debug=0 but wishes
267 to have all plug-ins run with --debug=1. This could be accomplished with the following call:
268 export AUTOBOOT_OVERRIDE_DEBUG=1 ; obmc_boot --debug=0 --plug_in_dir_paths=<list of plug ins>
269
270 As another example, let's suppose that the user wishes to have just the OS_Console plug-in run with debug
271 and everything else to default to debug=0. This could be accomplished as follows:
272 export OS_CONSOLE_DEBUG=1 ; obmc_boot --debug=0 --plug_in_dir_paths=<list of plug ins>
273
274 And as one more example, let's say the user wishes to have obmc_boot and OS_Console run without debug but
275 have all other plug-ins run with debug:
276 export AUTOBOOT_OVERRIDE_DEBUG=1 ; export OS_CONSOLE_DEBUG=0 ; obmc_boot --debug=0
Michael Walshf4c62a22017-11-13 15:40:57 -0600277 --plug_in_dir_paths=<list of plug ins>
278
Michael Walshf4c62a22017-11-13 15:40:57 -0600279 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500280 var_name The name of the variable for which a default value is to be calculated.
281 default The default value if one cannot be determined.
Michael Walshf4c62a22017-11-13 15:40:57 -0600282 """
283
284 var_name = var_name.upper()
285 plug_in_package_name = get_plug_in_package_name(case="upper")
286
287 package_var_name = plug_in_package_name + "_" + var_name
288 default_value = os.environ.get(package_var_name, None)
289 if default_value is not None:
290 # A package-name version of the variable was found so return its value.
291 return(default_value)
292
Michael Walsha6b46ed2018-06-01 14:31:23 -0500293 plug_var_name = PLUG_VAR_PREFIX + "_OVERRIDE_" + var_name
294 default_value = os.environ.get(plug_var_name, None)
Michael Walshf4c62a22017-11-13 15:40:57 -0600295 if default_value is not None:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500296 # A PLUG_VAR_PREFIX version of the variable was found so return its value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600297 return default_value
298
Michael Walsha6b46ed2018-06-01 14:31:23 -0500299 plug_var_name = PLUG_VAR_PREFIX + "_" + var_name
300 default_value = os.environ.get(plug_var_name, None)
Michael Walshf4c62a22017-11-13 15:40:57 -0600301 if default_value is not None:
Michael Walsh0cb727d2019-10-16 17:16:45 -0500302 # A PLUG_VAR_PREFIX version of the variable was found so return its value.
Michael Walshf4c62a22017-11-13 15:40:57 -0600303 return default_value
304
305 return default
306
307
Michael Walshe5599df2019-11-20 14:05:10 -0600308def required_plug_in(required_plug_in_names,
309 plug_in_dir_paths=None):
Michael Walshf4c62a22017-11-13 15:40:57 -0600310 r"""
Michael Walshe5599df2019-11-20 14:05:10 -0600311 Determine whether the required_plug_in_names are in plug_in_dir_paths, construct an error_message and
312 call gv.process_error_message(error_message).
313
314 In addition, for each plug-in in required_plug_in_names, set the global plug-in variables. This is
315 useful for callers who then want to validate certain values from other plug-ins.
Michael Walshf4c62a22017-11-13 15:40:57 -0600316
317 Example call:
Michael Walshe5599df2019-11-20 14:05:10 -0600318 required_plug_in(required_plug_in_names)
Michael Walshf4c62a22017-11-13 15:40:57 -0600319
320 Description of argument(s):
Michael Walshe5599df2019-11-20 14:05:10 -0600321 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 -0500322 plug_in_dir_paths A string which is a colon-delimited list of plug-ins specified by the
323 user (e.g. DB_Logging:FFDC:OS_Console:Perf). Path values (e.g.
324 "/home/robot/dir1") will be stripped from this list to do the analysis.
Michael Walshe5599df2019-11-20 14:05:10 -0600325 Default value is the AUTOGUI_PLUG_IN_DIR_PATHS or
326 <PLUG_VAR_PREFIX>_PLUG_IN_DIR_PATHS environment variable.
Michael Walshf4c62a22017-11-13 15:40:57 -0600327 """
328
329 # Calculate default value for plug_in_dir_paths.
Michael Walshe5599df2019-11-20 14:05:10 -0600330 plug_in_dir_paths = gm.dft(plug_in_dir_paths,
331 os.environ.get('AUTOGUI_PLUG_IN_DIR_PATHS',
332 os.environ.get(PLUG_VAR_PREFIX + "_PLUG_IN_DIR_PATHS", "")))
Michael Walshf4c62a22017-11-13 15:40:57 -0600333
334 # Convert plug_in_dir_paths to a list of base names.
335 plug_in_dir_paths = \
Michael Walsh6aa5a9e2018-08-07 15:04:56 -0500336 list(filter(None, map(os.path.basename, plug_in_dir_paths.split(":"))))
Michael Walshf4c62a22017-11-13 15:40:57 -0600337
Michael Walshe5599df2019-11-20 14:05:10 -0600338 error_message = gv.valid_list(plug_in_dir_paths, required_values=required_plug_in_names)
339 if error_message:
340 return gv.process_error_message(error_message)
Michael Walshf4c62a22017-11-13 15:40:57 -0600341
Michael Walshe5599df2019-11-20 14:05:10 -0600342 for plug_in_package_name in required_plug_in_names:
343 get_plug_vars(general=False, plug_in_package_name=plug_in_package_name)
Michael Walshf4c62a22017-11-13 15:40:57 -0600344
345
Michael Walsh96ffeb72018-08-23 11:37:22 -0500346def compose_plug_in_save_dir_path(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500347 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500348 Create and return a directory path name that is suitable for saving plug-in data.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500349
Michael Walsh0cb727d2019-10-16 17:16:45 -0500350 The name will be comprised of things such as plug_in package name, pid, etc. in order to guarantee that
351 it is unique for a given test run.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500352
353 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500354 plug_in_package_name The plug-in package name. This defaults to the name of the caller's
355 plug-in package. However, the caller can specify another value in order
356 to retrieve data saved by another plug-in package.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500357 """
358
Michael Walsh96ffeb72018-08-23 11:37:22 -0500359 plug_in_package_name = gm.dft(plug_in_package_name,
360 get_plug_in_package_name())
361
Michael Walsha6b46ed2018-06-01 14:31:23 -0500362 BASE_TOOL_DIR_PATH = \
Joy Onyerikwu004ad3c2018-06-11 16:29:56 -0500363 gm.add_trailing_slash(os.environ.get(PLUG_VAR_PREFIX
Michael Walsh2ce1dba2019-02-05 19:29:28 +0000364 + "_BASE_TOOL_DIR_PATH",
365 "/tmp/"))
Michael Walsha6b46ed2018-06-01 14:31:23 -0500366 NICKNAME = os.environ.get("AUTOBOOT_OPENBMC_NICKNAME", "")
367 if NICKNAME == "":
368 NICKNAME = os.environ["AUTOIPL_FSP1_NICKNAME"]
369 MASTER_PID = os.environ[PLUG_VAR_PREFIX + "_MASTER_PID"]
Michael Walshaa736b52019-11-20 14:14:31 -0600370 gp.dprint_vars(BASE_TOOL_DIR_PATH, NICKNAME, plug_in_package_name, MASTER_PID)
Michael Walsh2ce1dba2019-02-05 19:29:28 +0000371 return BASE_TOOL_DIR_PATH + gm.username() + "/" + NICKNAME + "/" +\
372 plug_in_package_name + "/" + str(MASTER_PID) + "/"
Michael Walsha6b46ed2018-06-01 14:31:23 -0500373
374
Michael Walsh96ffeb72018-08-23 11:37:22 -0500375def create_plug_in_save_dir(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500376 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500377 Create a directory suitable for saving plug-in processing data and return its path name.
Michael Walsh024a2f32019-04-18 10:55:34 -0500378
379 See compose_plug_in_save_dir_path for details.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500380
381 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500382 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500383 """
384
Michael Walsh96ffeb72018-08-23 11:37:22 -0500385 plug_in_save_dir_path = compose_plug_in_save_dir_path(plug_in_package_name)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500386 if os.path.isdir(plug_in_save_dir_path):
387 return plug_in_save_dir_path
388 gc.shell_cmd("mkdir -p " + plug_in_save_dir_path)
389 return plug_in_save_dir_path
390
391
Michael Walsh96ffeb72018-08-23 11:37:22 -0500392def delete_plug_in_save_dir(plug_in_package_name=None):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500393 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500394 Delete the plug_in save directory. See compose_plug_in_save_dir_path for details.
Michael Walsh96ffeb72018-08-23 11:37:22 -0500395
396 Description of argument(s):
Michael Walsh0cb727d2019-10-16 17:16:45 -0500397 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500398 """
399
Michael Walsh96ffeb72018-08-23 11:37:22 -0500400 gc.shell_cmd("rm -rf "
401 + compose_plug_in_save_dir_path(plug_in_package_name))
Michael Walsha6b46ed2018-06-01 14:31:23 -0500402
403
Michael Walshaa736b52019-11-20 14:14:31 -0600404def save_plug_in_value(var_value=None, plug_in_package_name=None, **kwargs):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500405 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500406 Save a value in a plug-in save file. The value may be retrieved later via a call to the
407 restore_plug_in_value function.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500408
Michael Walshaa736b52019-11-20 14:14:31 -0600409 This function will figure out the variable name corresponding to the value passed and use that name in
410 creating the plug-in save file.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500411
Michael Walshaa736b52019-11-20 14:14:31 -0600412 The caller may pass the value as a simple variable or as a keyword=value (see examples below).
413
414 Example 1:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500415
416 my_var1 = 5
417 save_plug_in_value(my_var1)
418
Michael Walsh0cb727d2019-10-16 17:16:45 -0500419 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 -0500420
Michael Walshaa736b52019-11-20 14:14:31 -0600421 Example 2:
422
423 save_plug_in_value(my_var1=5)
424
425 In this example, the value "5" would be saved to the "my_var1" file in the plug-in save directory.
426
Michael Walsha6b46ed2018-06-01 14:31:23 -0500427 Description of argument(s):
Michael Walshaa736b52019-11-20 14:14:31 -0600428 var_value The value to be saved.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500429 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walshaa736b52019-11-20 14:14:31 -0600430 kwargs The first entry may contain a var_name/var_value. Other entries are
431 ignored.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500432 """
433
Michael Walshaa736b52019-11-20 14:14:31 -0600434 if var_value is None:
435 var_name = next(iter(kwargs))
436 var_value = kwargs[var_name]
437 else:
438 # Get the name of the variable used as argument one to this function.
439 var_name = gp.get_arg_name(0, 1, stack_frame_ix=2)
Michael Walsh96ffeb72018-08-23 11:37:22 -0500440 plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500441 save_file_path = plug_in_save_dir_path + var_name
442 gp.qprint_timen("Saving \"" + var_name + "\" value.")
Michael Walshaa736b52019-11-20 14:14:31 -0600443 gp.qprint_varx(var_name, var_value)
444 gc.shell_cmd("echo '" + str(var_value) + "' > " + save_file_path)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500445
446
Michael Walshaa736b52019-11-20 14:14:31 -0600447def restore_plug_in_value(*args, **kwargs):
Michael Walsha6b46ed2018-06-01 14:31:23 -0500448 r"""
449 Return a value from a plug-in save file.
450
Michael Walshaa736b52019-11-20 14:14:31 -0600451 The args/kwargs are interpreted differently depending on how this function is called.
452
453 Mode 1 - The output of this function is assigned to a variable:
454
455 Example:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500456
457 my_var1 = restore_plug_in_value(2)
458
Michael Walshaa736b52019-11-20 14:14:31 -0600459 In this mode, the lvalue ("my_var1" in this example) will serve as the name of the value to be restored.
460
461 Mode 2 - The output of this function is NOT assigned to a variable:
462
463 Example:
464
465 if restore_plug_in_value('my_var1', 2):
466 do_something()
467
468 In this mode, the caller must explicitly provide the name of the value being restored.
469
470 The args/kwargs are interpreted as follows:
Michael Walsha6b46ed2018-06-01 14:31:23 -0500471
472 Description of argument(s):
Michael Walshaa736b52019-11-20 14:14:31 -0600473 var_name The name of the value to be restored. Only relevant in mode 1 (see
474 example above).
Michael Walsh0cb727d2019-10-16 17:16:45 -0500475 default The default value to be returned if there is no plug-in save file for the
476 value in question.
477 plug_in_package_name See compose_plug_in_save_dir_path for details.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500478 """
Michael Walshaa736b52019-11-20 14:14:31 -0600479 # Process args.
Michael Walsha6b46ed2018-06-01 14:31:23 -0500480 lvalue = gp.get_arg_name(0, -1, stack_frame_ix=2)
Michael Walshaa736b52019-11-20 14:14:31 -0600481 if lvalue:
482 var_name = lvalue
483 else:
484 var_name, args, kwargs = fa.pop_arg("", *args, **kwargs)
485 default, args, kwargs = fa.pop_arg("", *args, **kwargs)
486 plug_in_package_name, args, kwargs = fa.pop_arg(None, *args, **kwargs)
487 if args or kwargs:
488 error_message = "Programmer error - Too many arguments passed for this function."
489 raise ValueError(error_message)
Michael Walsh96ffeb72018-08-23 11:37:22 -0500490 plug_in_save_dir_path = create_plug_in_save_dir(plug_in_package_name)
Michael Walshaa736b52019-11-20 14:14:31 -0600491 save_file_path = plug_in_save_dir_path + var_name
Michael Walsha6b46ed2018-06-01 14:31:23 -0500492 if os.path.isfile(save_file_path):
Michael Walshaa736b52019-11-20 14:14:31 -0600493 gp.qprint_timen("Restoring " + var_name + " value from " + save_file_path + ".")
494 var_value = gm.file_to_list(save_file_path, newlines=0, comments=0, trim=1)[0]
Michael Walsh25f0f162018-09-10 13:57:11 -0500495 if type(default) is bool:
496 # Convert from string to bool.
Michael Walshaa736b52019-11-20 14:14:31 -0600497 var_value = (var_value == 'True')
Michael Walsh25f0f162018-09-10 13:57:11 -0500498 if type(default) is int:
499 # Convert from string to int.
Michael Walshaa736b52019-11-20 14:14:31 -0600500 var_value = int(var_value)
Michael Walsha6b46ed2018-06-01 14:31:23 -0500501 else:
Michael Walshaa736b52019-11-20 14:14:31 -0600502 var_value = default
503 gp.qprint_timen("Save file " + save_file_path + " does not exist so returning default value.")
504
505 gp.qprint_varx(var_name, var_value)
506 return var_value
Michael Walsha6b46ed2018-06-01 14:31:23 -0500507
508
Michael Walsh99beb652019-02-25 10:45:23 -0600509def exit_not_master():
510 r"""
Michael Walsh0cb727d2019-10-16 17:16:45 -0500511 Exit the program with return code zero if this program was NOT called by the master program.
Michael Walsh99beb652019-02-25 10:45:23 -0600512
513 There are cases where plug-ins are called by a multi-layered stack:
514
515 master_wrapper
516 obmc_boot_test.py
517 Example_plug_in/cp_setup
518
Michael Walsh0cb727d2019-10-16 17:16:45 -0500519 In a scenario like this, Example_plug_in/cp_setup may be called once directly by master_wrapper (the
520 master) and and then called again directly by obmc_boot_test.py (the child). Some plug-in programs may
521 wish to avoid doing any processing on the second such call. This function will achieve that purpose.
Michael Walsh99beb652019-02-25 10:45:23 -0600522
523 This function will print a standard message to stdout prior to exiting.
524 """
525
526 AUTOBOOT_MASTER_PID = gm.get_mod_global("AUTOBOOT_MASTER_PID")
527 AUTOBOOT_PROGRAM_PID = gm.get_mod_global("AUTOBOOT_PROGRAM_PID")
528
529 if AUTOBOOT_MASTER_PID != AUTOBOOT_PROGRAM_PID:
530 message = get_plug_in_package_name() + "/" + gp.pgm_name + " is not" \
531 + " being called by the master program in the stack so no action" \
532 + " will be taken."
533 gp.qprint_timen(message)
534 gp.qprint_vars(AUTOBOOT_MASTER_PID, AUTOBOOT_PROGRAM_PID)
535 exit(0)
536
537
Michael Walsh925294d2020-06-23 17:42:57 -0500538def add_tarball_tools_dir_to_path(quiet=0):
539 r"""
540 Find the directory containing the tarball tools and pre-pend it to PATH.
541
542 The calling program is responsible for making sure that the tarball has been unpacked.
543 """
544 AUTOBOOT_BASE_TOOL_DIR_PATH = gm.get_mod_global("AUTOBOOT_BASE_TOOL_DIR_PATH")
545 AUTOBOOT_OPENBMC_NICKNAME = gm.get_mod_global("AUTOBOOT_OPENBMC_NICKNAME")
546
547 tool_dir_path = AUTOBOOT_BASE_TOOL_DIR_PATH + os.environ.get('USER') + os.sep \
548 + AUTOBOOT_OPENBMC_NICKNAME + os.sep
549 tarball_tools_dir_path = tool_dir_path + 'tarball/x86/bin'
550 os.environ['PATH'] = gm.add_path(tarball_tools_dir_path, os.environ.get('PATH', ''))
551
552
Michael Walsh0cb727d2019-10-16 17:16:45 -0500553def stop_test_rc():
554 r"""
555 Return the constant stop test return code value.
556
557 When a plug-in call point program returns this value, it indicates that master program should stop
558 running.
559 """
560
561 return 0x00000002
562
563
Michael Walshf09e8af2020-05-05 13:54:15 -0500564def dump_ffdc_rc():
565 r"""
566 Return the constant dump FFDC return code value.
567
568 When a plug-in call point program returns this value, it indicates that FFDC data should be collected.
569 """
570
571 return 0x00000002
572
573
Michael Walshf4c62a22017-11-13 15:40:57 -0600574# Create print wrapper functions for all sprint functions defined above.
Michael Walsh0cb727d2019-10-16 17:16:45 -0500575# func_names contains a list of all print functions which should be created from their sprint counterparts.
Michael Walshf4c62a22017-11-13 15:40:57 -0600576func_names = ['print_plug_vars']
577
Michael Walsh0cb727d2019-10-16 17:16:45 -0500578# stderr_func_names is a list of functions whose output should go to stderr rather than stdout.
Michael Walshf4c62a22017-11-13 15:40:57 -0600579stderr_func_names = []
580
581replace_dict = dict(gp.replace_dict)
Michael Walsh81c02342018-01-05 15:43:28 -0600582replace_dict['mod_qualifier'] = 'gp.'
Michael Walshf4c62a22017-11-13 15:40:57 -0600583func_defs = gp.create_print_wrapper_funcs(func_names, stderr_func_names,
584 replace_dict)
585gp.gp_debug_print(func_defs)
586exec(func_defs)