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